[pgcluster: 913] Re: pgbench で固まってしまいます

Yoshiyuki Asaba y-asaba @ sraoss.co.jp
2006年 7月 27日 (木) 11:25:51 JST


おはようございます。浅羽です。

From: Eiichiro ITANI <emu @ ceres.dti.ne.jp>
Subject: [pgcluster: 911] Re: pgbench で固まってしまいます
Date: Wed, 26 Jul 2006 17:31:11 +0900

> > デッドロックするのは以下のような状況になります。
> 
> 〜略〜
> 
> > を実行すると、通常で更新する行が異なるのでロック待ちが発生しませんが、
> > 現在の PGCluster ではどちらかのデッドロックによりトランザクションがア
> > ボートしてしまいます。
> 
> なるほど、一般的なデッドロック発生と同じ条件ですね。
> 
> トランザクションブロックで囲まれていない(いわゆる AutoCommit = 1 の場
> 合)場合、問題ないのでしょうか?  トリガ、制約などであるテーブルに対する
> 更新が他のテーブルへも波及して行く場合、PostgreSQL 内部でトランザクショ
> ンを使った処理に展開されるのだろうと思うのですが。

外部キーがあると、PostgreSQL 8.1 の場合では SELECT FOR SHARE によるロ
ックが発生します。これは問題ないのですが、8.0 までだと SELECT FOR
UPDATE による行ロック獲得を行うので、こちらも注意する必要があります。


> > ShareRowExclusive 以上のレベルのテーブルロックを握ったままトランザクショ
> > ンを終了させずにクライアントが終了しますと、レプリケーションサーバがデッ
> > ドロックが発生する可能性がありました。1.0.10 に対するパッチを三谷さん
> > に送りましたが、お忙しいようなので、もしかしたらまだリリースされていな
> > いかもしれません。
> 
> 以前浅羽さんに頂いたパッチは 1.0.10 には当てていないのですが、これはも
> ともとの PGCluster 1.0、1.5 双方ともに可能性があるということでしょうか。

1.0.10 にはあのパッチは当てる必要はありません。上記のデッドロックはあ
のパッチで解決する問題とは別の問題であり、現在リリースされている
PGCluster では解決していない可能性があります。

具体的には、レプリケーションサーバではクラスタサーバ間でのデッドロック
が発生しないように、複数のトランザクションをシリアライズする必要があり
ます。そのため、レプリケーションサーバがレプリケーションする際にはある
ロックを獲得してから行います。

正しく COMMIT もしくは ABORT すれば、それは正しくレプリケーションされ
ますが、途中でトランザクションが終了した場合は、終了したということを別
のサーバに伝える必要があります。その「伝える」というところでもロックを
獲得してから伝えるようにしていたため、ロックを獲得できないと

  マスタ:トランザクション終了
  レプ1:クローズ処理していないのでトランザクション中
  レプ2:クローズ処理していないのでトランザクション中

という状態になります。この状態で別のクライアントがテーブルロックを獲得
すると、1 箇所だけロックを獲得することができる状態になります。こうなり
ますと、クラスタサーバ、レプリケーションサーバを含めたデッドロック状態
になってしまいます。

解決策は、「伝える」というところでレプリケーションサーバのロックを取る
必要が無いので送ってしまう、ということになります。

長文になってしまいましたが、以上になります。
--
Yoshiyuki Asaba
y-asaba @ sraoss.co.jp



pgcluster メーリングリストの案内