[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 メーリングリストの案内