LoginSignup
58
49

More than 5 years have passed since last update.

デッドロックの対策

Last updated at Posted at 2015-11-01

デッドロック事象

ここ数年聞かなかったけれど、身近なところで、立て続けにデッドロックが発生。事象は次のように簡略化して書くと、本当によくある典型的な事象。

トランザクションA トランザクションB
Key=1をUPDATE。
Key=2をUPDATE。
Key=2をUPDATE
==>トランザクションB待ち
Key=1をUPDATE
==>デッドロック‼!

しかし、何でだろう?と思い、もう少し聞いてみたら、そうだねぇと思うところもあったので、注意喚起を込めて書いています。

デッドロック具体的例

これまでは、jsp+servletでしたが、最近、リッチクライアント化したアプリ。クライアント側のグリッド上で自由にソートしてデータを並べかえられるようになりました。その結果、

1):トランザクションAは、グリッドを昇順ソートした後で更新。
2):トランザクションBは、グリッドを降順ソートした後で更新。

のために、ロックがたすき掛けになって、デッドロックとなりました。
解ってしまえば、そりゃそうだよねだし、何で気がつかなかった、気づいてあげられなかったんだろうと。
ということで、教訓。

教訓

グリッドで自由にソートできるとするなら、更新順番には気を付けろ!
です。

最後に、私の場合のデッドロック対策。

設計に入る前のプロジェクトキックオフで、この手のよくある不具合(nullの扱いとか)について、
こんな事例があってとか、このプロジェクトではどうするとかを話します。
いつも同じメンバならよいのですが、そうじゃないときもあるので。
これでメンバの心のどこかに引っ掛かりができると思っています(思いたい)。

あとは、設計時、実装時の「レビュー」による、回避策です。

レビュー時の問いかけフレーズ
Aさん、Bさんと複数の人が、その画面からの更新が並列して行えるとして、
 その画面から一回の指示で複数レコードを更新するとしたら、その順序は?
 その画面から一回の指示で複数テーブルを更新するとしたら、その順序は?

オンライン処理とバッチ処理が並列して行えるとして、
 オンライン処理とバッチ処理で複数レコードを更新するとしたら、その順序は?
 オンライン処理とバッチ処理で複数テーブルを更新するとしたら、その順序は?

デッドロック回避策の定義:

回避:複数のトランザクションで、同じ資源のロックが必要なら、同じ順序でロックを取得する。
この順序は、人力に委ねられているため、設計時のミス、実装時のミスをしたら、デッドロックしてしまう。
 
受容:タイムアウトを指定。デッドロックが検知され、負けた方が、ABEND、もしくはもう一度トランザクションをやり直す。==>トランザクションのやり直しができるということは、そこでデッドロックが起きるとわかっているので、回避に向けた実装ができる。ABENDは、運用保守チームからすると、Noooo、受け入れたくないです。

軽減:トランザクション内の処理時間を短くすることで、デッドロックを起きにくくする。==>どんだけ早くするば?!

転嫁:思い付かない。あるのかな?

参考:mysqlでデドロックを試す

トランザクションAが倉庫ID=1の商品ID=1234567-01、商品ID=1234567-02の順でロックを取得し、トランザクションBが倉庫ID=1の商品ID=1234567-02、商品ID=1234567-01の順でロックを取得するようなたすき掛けで、デッドロックが発生する様子を見る。

テーブルの初期状態

初期状態
mysql> SELECT
    ->  *
    -> FROM
    ->  T_STOCK
    -> WHERE
    ->  STOCKHOUSE_ID='1'
    -> ;
+---------------+------------+--------+--------+---------------------+
| STOCKHOUSE_ID | ITEM_ID    | AMOUNT | VER_ID | UPD_DTTM            |
+---------------+------------+--------+--------+---------------------+
|             1 | 1234567-01 |    123 | 1      | 2015-09-23 16:33:52 |
|             1 | 1234567-02 |    600 | 1      | 2015-09-23 16:33:52 |
|             1 | 1234567-03 |    702 | 1      | 2015-09-23 16:33:52 |
|             1 | 1234567-04 |    395 | 1      | 2015-09-23 16:33:52 |
|             1 | 1234567-05 |    903 | 1      | 2015-09-23 16:33:52 |
|             1 | 1234567-06 |    679 | 1      | 2015-09-23 16:33:52 |
|             1 | 1234567-07 |      2 | 1      | 2015-09-23 16:33:52 |
|             1 | 1234567-08 |    158 | 1      | 2015-09-23 16:33:52 |
|             1 | 1234567-09 |    518 | 1      | 2015-09-23 16:33:52 |
|             1 | 1234567-10 |    456 | 1      | 2015-09-23 16:33:52 |
+---------------+------------+--------+--------+---------------------+
10 rows in set (0.00 sec)

トランザクションA、Bでそれぞれたすき掛けのロックを取得したときの挙動

image

58
49
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
58
49