[pgcluster: 444] SELECT FOR UPDATE のデッドロックについて

Yusuke Ito y-110 @ yumemi.co.jp
2004年 8月 4日 (水) 16:42:23 JST


お世話になります。
伊藤と申します。

pg_cluster1.0.7を利用しておりますが、select for update のロックの挙動について
気になる点がありましたので、投稿させていただきます。

# [pgcluster:439] と関連する内容と判断し、レスをつける形で投稿しました

[pgcluster:236] [pgcluster:439] と類似の報告となるかと思いますが、
select for update を含むトランザクションにて、デッドロックを発生させる
クエリを発行した際に、psql からの応答がなくなるという現象が発生しております。

【サーバ構成】
 レプリケーションサーバ(R1,R2)	2台
 クラスタサーバ	(C1,C2,C3)	3台
 PGCluster	1.0.7v10

 レプリケーションサーバのスレーブが FreeBSD 5.2.1-RELEASE-p9,
 その他4台のサーバが Debian GNU 3.0 の構成。

 ロードバランサは使用しておらず、プログラムでランダムにC1〜C3に接続するようになっています。
 接続は PHP の pconnect 関数を使用して接続。


【前提】
 create table a(int id) を実行し、1〜10 までを insert しておく。
 また、他のテーブルにランダムに SELECT を発行するようなプログラムを起動しておく。

【手順】
 1. C1 に接続し、以下の select for update を実行。
test=> begin;
test=> select id from a where id = 8 for update;
  id 
 ----
   8
 (1 row)

 2. C2 に接続し、以下の select for update を実行
test=> begin;
test=> select id from a where id = 7 for update;
  id 
 ----
   7
 (1 row)

 3. デッドロックが起こるように、それぞれ相手のリソースを select for update.
 C1 test=> select id from a where id = 7 for update;
 C2 test=> select id from a where id = 8 for update;

 ここでデッドロックが発生し、両方のターミナルからの応答がなくなる。

 4. しばらく待つと C2 の入力がアクティブになる。C1は応答がないまま。

 このタイミングで C1 の postmaster のログには以下のログがひたすら流れ続ける。

2004-08-03 20:59:02 [31505]  LOG:  pq_recvbuf: unexpected EOF on client connection
2004-08-03 20:59:02 [31505]  LOG:  pq_recvbuf: unexpected EOF on client connection
2004-08-03 20:59:02 [31505]  LOG:  pq_recvbuf: unexpected EOF on client connection

 入力が戻った C2 で再度、以下の select for update を実行するとやはり応答が帰ってこないままだった。
 C2=> select id from a where id = 8 for update;

【結果】
 一度、この現象が発生すると、自動スクリプトが走っている間に pg_locks テーブルの要素が
どんどん増えていき、最終的にシステムが不安定になり、C1〜C3 に全くアクセスができなくなる。
 pg_stat_activity.current_query には、BEGIN, ROLLBACK, idle, idle in transaction が大量にある。
# BEGIN と ROLLBACK は pconnect によるものでしょうか...

何度か同様の実験を試みたが、この状態から回復するには、C1〜C3, R1, R2 を止めて、再起動するしかなかった。
レプリケーションサーバ1台の構成(全てDebian 3.0構成)でも試してみましたが、結果は同様でした。


今回は、select for update で意図的にデッドロックを発生させましたが、
一度、select for update でデッドロックが発生すると、応答がない状況になってしまうのでしょうか?

尚、C1〜C3 の deadlock_timeout の設定はデフォルト(1000ms) のままになっております。

# 同様の実験をスタンドアロンの Postgres で行いましたが、即座にデッドロックが検出されました。

+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
Yusuke Ito <y-110 @ yumemi.co.jp>
Work Phone: 090-4708-2445
Yumemi, Inc
________________________________i___
|   |   | | |   |   |  _|   |   | _ |
|_     _|   |       |  _|       ||_||
  |___| |___|_|___|_|___|_|___|_|:::|
                                |:::|
                                |___|




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