[pgsql-jp: 35294] Re: pgpoolのreplication_stop_on_mismatch について
Tsunehisa Kazawa
kazawa @ ca2.so-net.ne.jp
2005年 4月 19日 (火) 23:10:27 JST
加澤です。pgpool を使った HA へのチャレンジの続報です。
// また長くなってしまった…。
Tsunehisa Kazawa wrote:
> 石井さんのおっしゃるとおり、SELECT を明示的なトランザクションブロックに
> 含めるだけでトランザクション終了まで ACCESS SHARE ロックが確保されたまま
> となるようになり、目的通りの動作とすることが出来ました。どうもありがとう
> ございます。
昨日上記のようにご報告したのですが、その後さらにしつこくテストをしていた
ところ、master 側と secondary 側のロック順序が入れ替ってしまって pgpool
が deadlock する、という現象が起こりました。
バックエンドに直接接続して pg_locks を確認してみると (最初 pgpool 経由で
pg_locks を確認したところ一撃で縮退してしまって驚きました・笑。考えてみ
れば当たり前)、master 側では ACCESS EXCLUSIVE ロックにより ACCESS SHARE
ロック作成をブロックされているトランザクションが、なぜか secondary 側で
は先に ACCESS SHARE ロックを取得できてしまっていて、そのため master で
ACCESS EXCLUSIVE ロック確保しているトランザクションが secondary 側での
ACCESS EXCLUSIVE ロック取得をブロックされてしまって deadlock してしまっ
た、ということのようでした。
// ちなみに pgpool レベルで deadlock してしまうと
// PostgreSQL から見ると単なるアプリケーションレベル
// のロック待ちのようにしかみえないため、外部から強制
// 的にコネクションを切断するなりしてあげないとずっと
// アプリケーションがロックアップ状態になってしまいま
// す。
どうしてそのような状況が起こるのか、pgpool-2.5.2 のソースを確認してみた
ところ、pool_process_query.c の 2227 行目付近で、strict モードの場合でも
SQL が「SELECT」(大文字、小文字問わず) から始まっている場合は master 側
コネクションからの返事を待たず、secondary 側へ write しているらしいこと
が分かり (2.5.2 で修正された箇所でしょうか)、そうすると master 側が
ACCESS EXCLUSIVE ロックによりブロックされている場合でも secondary 側へ
SELECT が投げられ、ACCESS SHARE ロックを先に確保してしまう場合があるので
はないかと考えました。
もしその認識が正しいとすると、解決方法としては、
・SELECT にも頭に /*STRICT*/ を付ける (本当は /*STRICT*/ でなくても何で
も良い)。
・SELECT の前に明示的に LOCK TABLE 〜 IN ACCESS SHARE MODE する。
といったことが考えられます。
前者の場合、SELECT もシーケンシャルに処理されるようになってしまうため、
特に count(*) 系や ORDER BY などを用いたいわゆる「重い」query 時の性能劣
化が心配です。そこで、今回は後者で対応してみることにしました。こちらなら
ば SELECT 自体はパラレルに動作出来ます。
これは余談ですが、SELECT で始まる場合は無条件に master/secondary 双方同
時に write してしまう今のコードですと、ACCESS EXCLUSIVE ロックを使わない
場合でも、例えば SELECT FOR UPDATE などのコードで deadlock してしまう可
能性がありそうに思います。deadlock する可能性のある SQL では、たとえ
replication_strict = true で運用することが決まっているのだとしても、
/*STRICT*/ 指示子を付けておいた方が安全、ということかもしれません。
以上、ご報告でした。それではまた。
--
◇ 加澤恒央 Tsunehisa KAZAWA
◇ ◇ mailto:kazawa @ ca2.so-net.ne.jp
◇ http://www.digitune.org/
pgsql-jp メーリングリストの案内