[pgsql-jp: 40830] Re: デッドロックについて
TAKATSUKA Haruka
harukat @ postgresql.jp
2011年 6月 29日 (水) 11:54:00 JST
高塚です。
インラインでコメントします。
On Tue, 28 Jun 2011 22:19:06 +0900
<nozawakz @ nttdata.co.jp> wrote:
> ORDER BY 主キーを設定したところ
> デッドロックは発生しなくなりました。
> (テーブルロックに関しても実施してみます。)
# 後から気づきましたが、
# WHERE句で条件付けていないなら「断じてテーブルロックすべきだ」
# と言うべきですね。テーブル全体を SELECT FOR UPDATE して得をする
# ことはなさそうです。
> デッドロックは発生しなくなりましたが
> 私が知識不足であるため、大変お手数ですが、
> デッドロックが発生しなくなった理由について
> 私の理解が合っているか確認させていただけないでしょうか。
>
> 下記のように
> トランザクション1のselect for update文で
> 4レコードの順序が
> A→B→C→Dの順になっているとする。
>
> 次にUpdate文でBのレコードを更新しようとする。
> この際、2行目以外はロックを解放する。
ここは間違っています。
ロックはトランザクション最後にすべて解放されます。
> トランザクション2では不定であるため、
> B→C→D→A
> となってしまっているとすると、
> トランザクション1で
> Update文がcommitされる前に
SELECT FOR UPDATE の一文の動作自体が、各行を順に行ロックしていく、
というもので、他のトランザクションと並行で動作していきます。
そして、行単位で競合すればロック待ちが生じるということです。
> トランザクション2のselect for update文で
> 1,3,4行目をロックしてしまい、Bをロックしてしまうため、
> トランザクション1でBのレコードを更新完了できない。
>
> 上記が連鎖的にトランザクション3以降でも
> 起こるため、デッドロックが発生する。
>
> [トランザクション1]
> A
> B
> C
> D
>
> [トランザクション2]
> B
> C
> D
> A
>
> [トランザクション3]
> A
> D
> C
> B
>
>
> 以上、よろしくお願いいたします。
>
> ________________________________________
> 差出人: pgsql-jp-bounces @ ml.postgresql.jp [pgsql-jp-bounces @ ml.postgresql.jp] は TAKATSUKA Haruka [harukat @ postgresql.jp] の代理
> 送信日時: 2011年6月28日 18:44
> 宛先: PostgreSQL Japanese Mailing List
> 件名: [pgsql-jp: 40827] Re: デッドロックについて
>
> 高塚 @ JPUG / SRA OSS,Inc. と申します。
>
> これはデッドロックは出ます。
> 以下で出なくなると思います。
>
> (1') SQL1
> SELECT カラムA、カラムB、カラムc
> FROM 業務テーブルA
> ORDER BY 主キー
> FOR UPDATE;
>
> 行ロック順序が不定なので、行ロックがたすきがけになっているのでしょう。
>
> # 小さいテーブルと分かっているならテーブルロックでもいんじゃない?
> # とも思います。
>
> On Tue, 28 Jun 2011 18:03:58 +0900
> <nozawakz @ nttdata.co.jp> wrote:
>
> > お世話になります。野沢と申します。
> >
> > デッドロックの現象が解決しないため、質問させてください。
> > RHEL5.5 64bit,Postgresql8.4.5
> >
> > ○質問事項
> > レコード件数が少ないテーブルに対して複数トランザクションで
> > Update文を発行する場合、デッドロックが発生することは
> > ありえますでしょうか。
> > また、解析方法で有効な手段があればご教授お願いできないでしょうか。
> >
> > ○現象
> > <SQLについて>
> > 下記(1)、(2)の順でSQLが発行されます。
> > (1)SQL1
> > SELECT カラムA、カラムB、カラムc
> > FROM 業務テーブルA
> > FOR UPDATE;
> >
> > (2)SQL2
> > UPDATE 業務テーブルA
> > SET カラムC = SQL(1)で取得した値
> > WHERE カラムA = カラムAの値
> > AND カラムB = カラムBの値
> >
> > <業務テーブルA>
> > 合計4レコードのみ
> >
> > <デッドロックが発生した時の状況>
> > (1)SQL発行頻度
> > テストでは80TPSの負荷をかけて、上記SQL文を発行しました。
(後略)
pgsql-jp メーリングリストの案内