MySQLのデッドロック対処 おまけでギャップロック

ホーム > 業務日誌 > スタッフ別 > > MySQLのデッドロック対処 おまけでギャップロック

デッドロック

どうも!デッドロック撲滅委員会会長の優です。

今回はトランザクションでよくありがちなデッドロックのご紹介。

 

デッドロックとは、複数のプロセスが互いに相手の占有している資源の解放を待ってしまい、処理が停止してしまうこと。データベースの排他制御の不備などが原因で起こる。

資源aを占有する処理Aと資源bを占有する処理Bが並列に実行されており、Aが次の処理にbを、Bが次の処理にaを利用したい場合、AとBは互いに相手が資源を解放するのを待ってしまい、どちらも処理が停止してしまう。AやBの処理内容自体に誤りが無くても起きるため、原因不明の不具合としてなかなか発見されないことが多い。

@see e-Words

引用文に原因不明とありますがその通りで。DBが何故か落ちるという相談を頂くことがあります。

 

 

『DBが時々落ちる』という相談を受けたら、デッドロックを疑う!!

  • トランザクション命令が行われているテーブルで、なぜかストレージエンジンがMyISAM(!!)
    →InnoDBに変更する必要があります。
  • ロールバック時のエラー制御の仕組みがない。
    プログラムでロールバックや検知の仕組みの実装。
    また、ロックする順番や制御などの検証を行い根本的解決を行います。

DBが固まったり、落ちると聞くシステムの引継ぎの際はチェックをすると良いかもしれません。

 

バックナンバー

 

 

たすきがけのデッドロック

デッドロック たすきがけ

よくデッドロックはなんぞや?といった時に提示されるパターンです。

 

 

 

デッドロック

 

解決には?

デッドロック

テーブルへの書き込みの順番を揃えてあげることで解決です!

簡単ですね!

 

 

外部キー制約によるデッドロック

外部キー制約があるテーブルはINSERT時に親テーブルに共有ロックがかかります。

 

 

 

 

 

 

たすきがけになっていないはずなのに…どうして?

何気に見逃しがちなパターンです。

 

解決

デッドロック

外部キー制約がされているテーブルを操作する前に、親のテーブルに対して先に排他ロックをかけておきます。

 

 

 

すぐに対応が出来ない!

設計の見直しや検証が終わるまで対症療法として、デッドロックになっても早くタイムアウトするようにしておく、という手もあります。

 

/etc/my.cnf

 

プログラムでロールバックする

また、プログラム側でデッドロックを検地した場合はロールバックする仕組みを実装することも出来ます。

 

ロールバックの仕組みの実装と同時にデッドロック時にログに出力するようにしたり、メールなどの通知でデッドロックを検知する仕組みを実装すると良いかもしれませんね!

 

 

ギャップロック

ギャップロック: これはインデックスレコード間にあるギャップのロック、または先頭のインデックスレコードの前や末尾のインデックスレコードのあとにあるギャップのロックです。

@see https://dev.mysql.com/doc/refman/5.6/ja/innodb-record-level-locks.html

インデックスの空振りロックです。

 

 

 

 

パターン1 排他ロックで対象IDにレコードが存在しない場合

 

Aトランザクション

 

Bトランザクション

 

Aトランザクション

ギャップロックがかかる。

 

 

パターン2  指定IDの排他ロックを空振りした場合

 

Aトランザクション

 

Bトランザクション

 

ギャップロックがかかる。

 

 

モード、トランザクション!

降順SELECTと昇順SELECTソートで魂のロックをぶつけろ!

 

DBは奥が深いですね。

お疲れ様です。

金広 優(エンジニア)

この記事を書いた人:金広 優(エンジニア)

システムガーディアン爆弾処理班。アクセス負荷対策やNginxへの移行案件が多いこの頃。IBM BlueMix InfrastructureやAWSなどクラウド案件が多くなってきました。

この記事に関してのお問い合わせ
御連絡・ご返信は原則2営業日以内を予定しております。
お急ぎの場合は、お手数ですが下記電話でもご対応をしております。

システムガーディアン株式会社
受付時間:平日9:00~18:00
受付担当:坪郷(つぼごう)・加藤
電話:03-6758-9166