[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.jphttp://www.digitune.org/



pgsql-jp メーリングリストの案内