谷本 心 in せろ部屋

はてなダイアリーから引っ越してきました

1テーブルでも起きるデッドロック

いや、この業界に5年もいて知らなかったのかよ、って言われれば
言い返せないことなんですが・・・


試験中に、Oracleデッドロックが発生しました。


でも、ソースコードをレビューした限りでは、
複数テーブルに対するupdateにもselect for updateにも、怪しい所はなく、
「試験のやり方が悪いんじゃね?」ぐらいの勢いでした。


でも違いました。
1テーブルへのアクセスでも、デッドロックは発生するということでした。

2. 複数レコードの更新に関するもの
当然のことながら、1つのテーブルでも、デッドロックが発生する場合がある。
上記のパターンで同一テーブル内でも A, B という異なるレコードに連続してアクセスする場合には、アクセス順を一意にしておかないとデッドロックが発生する要因となる。


特に陥りやすいのは、複数レコードを一括して更新する場合は更新順が一般に不定となるため、安易に使用するとデッドロックが発生しやすい。


対策:
 ・ 複数レコード更新の際はカーソルを使用する。(FOR UPDATE をつける)
 ・ カーソルのSELECT文では必ずORDER BYを指定し、その順を規定しておく。

デッドロックを回避するための方策 - okalabo


ちなみに、Oracle9iで試している限りは、
1テーブルに対する、order byをつけたselect for update同士でも、
複数レコードを更新するupdate同士でも、デッドロックが発生していました。
まだ、あまり原因は追究していませんが。


とりあえず、複数レコードに対するレコードロックでも
デッドロックが発生しないか、気をつけるようにします。