2010年2月13日

[pgsql-jp: 40166]子テーブルの2回目の更新でデッドロック

こんにちは、平塚といいます。

外部キー制約のあるテーブルで、子テーブルの2回目の更新で
デッドロックが発生するという事象に悩まされています。
PostgreSQL 8.4.2です。

create table parent (k int primary key, d varchar(10));
create table child (k int primary key, f int, d varchar(10),

constraint child_fk1 foreign key (f) references parent (k));

insert into parent values (1, 'a');
insert into parent values (2, 'b');

insert into child values (11, 1, 'aa');
insert into child values (12, 2, 'bb');

client1> begin;
client1> update parent set d = 'a2' where k = 1;

client2> begin;
client2> update parent set d = 'b2' where k = 2;
client2> update parent set d = 'a3' where k = 1; -- blocked

client1> update child set d = 'bb2' where k = 12; -- ok
client1> update child set d = 'bb3' where k = 12; -- deadlock

ERROR: deadlock detected
DETAIL: Process 307 waits for ShareLock on transaction 80443;
blocked by process 311.
Process 311 waits for ShareLock on transaction 80442;
blocked by process 307.
HINT: See server log for query details.
CONTEXT: SQL statement "SELECT 1 FROM ONLY "public"."parent" x
WHERE "k" OPERATOR(pg_catalog.=) $1 FOR SHARE OF x"

1回目の「update child set d = 'bb2' where k = 12」は通るのに、
同じSQLをもう1回投げるとデッドロックになるのが不思議です。

プログラム自体はリトライするように直しているところですが、
これはどういう仕組みで発生しているのでしょうか。


処理の流れを単純化すると、
以下のシーケンスで2回目の更新がブロックされています。

client1> begin;
client1> update parent set d = 'a2' where k = 1;

client2> begin;
client2> update child set d = 'aa2' where k = 11; -- ok
client2> update child set d = 'aa3' where k = 11; -- blocked


以下の記事は拝見しました。8.1以降なら大丈夫かと思ったのですが…。
http://itpro.nikkeibp.co.jp/article/COLUMN/20050904/220557/?ST=oss&P=3

よろしくお願いいたします。

--
平塚貞夫 <sh2@xxxxx>


投稿者 xml-rpc : 2010年2月13日 11:38
役に立ちました?:
過去のフィードバック 平均:(0) 総合:(0) 投票回数:(0)
本記事へのTrackback: http://hoop.euqset.org/blog/mt-tb2006.cgi/93273
トラックバック
コメント
コメントする




画像の中に見える文字を入力してください。