序文 これまで遭遇したデータベースのデッドロックはすべて、バッチ更新中のロック順序の不一致が原因でしたが、先週は非常に理解しにくいデッドロックに遭遇しました。この機会に、MySQL のデッドロックに関する知識と一般的なデッドロックのシナリオを再学習しました。多くの調査と同僚との議論を経て、私はついにデッドロック問題の原因を発見し、多くのことを得ることができました。私たちはバックエンドプログラマーですが、DBAほど深くロック関連のソースコードを分析する必要はありませんが、基本的なデッドロックのトラブルシューティング方法を習得できれば、日々の開発に大きなメリットをもたらします。 PS: この記事ではデッドロックの基礎知識は紹介しません。MySQL のロック原理については、この記事の参考資料に記載されているリンクを参照してください。 デッドロックの原因 まずはデータベースとテーブル状況を紹介します。社内の実際のデータを扱うため、以下はシミュレーションであり、具体的な分析には影響しません。 MySQL データベース バージョン 5.5 を使用し、トランザクション分離レベルはデフォルトの RR (Repeatable-Read) で、InnoDB エンジンを使用します。次のテスト テーブルがあると仮定します。 テーブル「test」を作成します( `id` int(11) 符号なし NOT NULL AUTO_INCREMENT, `a` int(11) 符号なし DEFAULT NULL, 主キー (`id`)、 ユニークキー `a` (`a`) ) ENGINE=InnoDB AUTO_INCREMENT=100 デフォルトCHARSET=utf8; テーブルの構造は非常にシンプルで、主キー id と別の一意のインデックス a があります。表のデータは次のとおりです。 mysql> テストから * を選択します。 +----+------+ | id | a | +----+------+ | 1 | 1 | | 2 | 2 | | 4 | 4 | +----+------+ セット内の 3 行 (0.00 秒) デッドロックの原因となる操作は次のとおりです。
次に、 ------------------------ 最近検出されたデッドロック ------------------------ 170219 13:31:31 *** (1)取引: トランザクション 2A8BD、アクティブ 11 秒開始インデックス読み取り 使用中の MySQL テーブル 1、ロックされているテーブル 1 LOCK WAIT 2 ロック構造体、ヒープ サイズ 376、1 行ロック MySQL スレッド ID 448218、OS スレッド ハンドル 0x2abe5fb5d700、クエリ ID 18923238 renjun.fangcloud.net 121.41.41.92 ルート更新中 a = 2 のテストから削除 *** (1) このロックが許可されるのを待機しています: レコードロック スペース ID 0 ページ番号 923 n ビット 80 テーブル `oauthdemo`.`test` のインデックス `a` トランザクション ID 2A8BD ロック モード X 待機中 レコード ロック、ヒープ番号 3 物理レコード: n_fields 2; コンパクト フォーマット; 情報ビット 32 0: 長さ 4; 16 進数 00000002; 昇順 ;; 1: 長さ 4; 16 進数 00000002; 昇順 ;; *** (2)取引: トランザクション 2A8BC、アクティブ 18 秒挿入 使用中の MySQL テーブル 1、ロックされているテーブル 1 4 つのロック構造体、ヒープ サイズ 1248、3 つの行ロック、UNDO ログ エントリ 2 MySQL スレッド ID 448217、OS スレッド ハンドル 0x2abe5fd65700、クエリ ID 18923239 renjun.fangcloud.net 121.41.41.92 ルート更新 テスト(id、a)の値(10、2)に挿入 *** (2) ロックを保持する: レコード ロック スペース ID 0 ページ番号 923 n ビット 80 テーブル `oauthdemo`.`test` のインデックス `a` trx ID 2A8BC lock_mode X はレコードをロックしますが、ギャップはロックしません レコード ロック、ヒープ番号 3 物理レコード: n_fields 2; コンパクト フォーマット; 情報ビット 32 0: 長さ 4; 16 進数 00000002; 昇順 ;; 1: 長さ 4; 16 進数 00000002; 昇順 ;; *** (2) このロックが許可されるのを待機しています: レコード ロック スペース ID 0 ページ番号 923 n ビット 80 テーブル `oauthdemo`.`test` のインデックス `a` トランザクション ID 2A8BC ロック モード S 待機中 レコード ロック、ヒープ番号 3 物理レコード: n_fields 2; コンパクト フォーマット; 情報ビット 32 0: 長さ 4; 16 進数 00000002; 昇順 ;; 1: 長さ 4; 16 進数 00000002; 昇順 ;; *** トランザクションをロールバックします (1) 分析する デッドロックログの読み取り デッドロックが発生した場合、最初のステップはデッドロック ログを読むことです。デッドロック ログは通常 2 つの部分に分かれています。最初の部分には、トランザクション 1 が待機しているロックが表示されます。 170219 13:31:31 *** (1)取引: トランザクション 2A8BD、アクティブ 11 秒開始インデックス読み取り 使用中の MySQL テーブル 1、ロックされているテーブル 1 LOCK WAIT 2 ロック構造体、ヒープ サイズ 376、1 行ロック MySQL スレッド ID 448218、OS スレッド ハンドル 0x2abe5fb5d700、クエリ ID 18923238 renjun.fangcloud.net 121.41.41.92 ルート更新中 a = 2 のテストから削除 *** (1) このロックが許可されるのを待機しています: レコードロック スペース ID 0 ページ番号 923 n ビット 80 テーブル `oauthdemo`.`test` のインデックス `a` トランザクション ID 2A8BD ロック モード X 待機中 レコード ロック、ヒープ番号 3 物理レコード: n_fields 2; コンパクト フォーマット; 情報ビット 32 0: 長さ 4; 16 進数 00000002; 昇順 ;; 1: 長さ 4; 16 進数 00000002; 昇順 ;; ログから、トランザクション 1 が現在 ログの下半分には、トランザクション 2 が現在保持し、待機しているロックが表示されます。 *** (2)取引: トランザクション 2A8BC、アクティブ 18 秒挿入 使用中の MySQL テーブル 1、ロックされているテーブル 1 4 つのロック構造体、ヒープ サイズ 1248、3 つの行ロック、UNDO ログ エントリ 2 MySQL スレッド ID 448217、OS スレッド ハンドル 0x2abe5fd65700、クエリ ID 18923239 renjun.fangcloud.net 121.41.41.92 ルート更新 テスト(id、a)の値(10、2)に挿入 *** (2) ロックを保持する: レコード ロック スペース ID 0 ページ番号 923 n ビット 80 テーブル `oauthdemo`.`test` のインデックス `a` trx ID 2A8BC lock_mode X はレコードをロックしますが、ギャップはロックしません レコード ロック、ヒープ番号 3 物理レコード: n_fields 2; コンパクト フォーマット; 情報ビット 32 0: 長さ 4; 16 進数 00000002; 昇順 ;; 1: 長さ 4; 16 進数 00000002; 昇順 ;; *** (2) このロックが許可されるのを待機しています: レコード ロック スペース ID 0 ページ番号 923 n ビット 80 テーブル `oauthdemo`.`test` のインデックス `a` トランザクション ID 2A8BC ロック モード S 待機中 レコード ロック、ヒープ番号 3 物理レコード: n_fields 2; コンパクト フォーマット; 情報ビット 32 0: 長さ 4; 16 進数 00000002; 昇順 ;; 1: 長さ 4; 16 進数 00000002; 昇順 ;; ログの では、なぜ S ロックが失敗するのでしょうか?つまり、同じフィールドのロックのアプリケーションはキューに入れる必要があります。 S ロックの前に失敗した X ロックがあるため、S ロックは待機する必要があり、循環待機が形成され、デッドロックが発生します。 デッドロック ログを読むことで、2 つのトランザクションによってどのような循環待機が形成されているかを明確に知ることができます。さらに分析すると、循環待機の原因、つまりデッドロックの原因を逆に推測できます。 デッドロック形成フローチャート デッドロックの原因をよりよく理解できるように、デッドロックの形成プロセスを表の形式で説明します。
拡大する デッドロックのトラブルシューティング プロセス中に、同僚は、上記のシナリオでは別のデッドロックが発生することを発見しました。このデッドロックは手動では再現できず、同時実行性の高いシナリオでのみ再現できます。 このデッドロックに対応するログはここには掲載されていません。 デッドロック生成のプロセスを詳しく説明するために、表を使用します。
要約する デッドロックのトラブルシューティングを行うときは、まずデッドロック ログに基づいて循環待機のシナリオを分析し、次に現在の各トランザクションによって実行された SQL に基づいてロックの種類とシーケンスを分析し、循環待機がどのように形成されたかを逆に推測する必要があります。このようにして、デッドロックの原因を見つけることができます。 さて、この記事はこれで終わりです。この記事の内容が皆さんの勉強や仕事に少しでも役立てば幸いです。上記の分析は経験に基づいています。他の友人が間違いや欠陥を指摘してくれることを願っています。123WORDPRESS.COM へのご支援ありがとうございます。 以下もご興味があるかもしれません:
|
<<: Linux で top コマンドを使用する際のヒント
>>: jQueryはhide()とtoggle()関数を使用してカメラブランド表示の非表示機能を実現します。
序文:ジュニアプログラマーとして、私は自分自身の個人ウェブサイトを構築し、それを他の人に見せることを...
この記事では、Docker+Jenkins の自動ビルドデプロイメントを紹介し、皆さんと共有します。...
序文会社の業務上のニーズにより、独自の MongoDB サービスを構築する予定です。MongoDB ...
目次まず多次元配列の平坦化についてお話しましょう方法 1: flat()方法 2: 空の文字列を連結...
1. テキストの書式設定: この例では、HTML ファイル内のテキストを書式設定する方法を示します...
達成される効果は、固定ズームが 2 倍になり、マウスが左側の画像領域に入るとマスク レイヤーが表示さ...
ウェブサイト構築におけるカラーマッチングは非常に特殊であり、ウェブサイトのテーマ、感情、雰囲気などの...
面接では、次のようなシナリオを経験する必要があります。インタビュアー: 「MySQL を使用したこと...
CHAR 型と VARCHAR 型は似ていますが、主に格納場所、末尾のスペース、取得方法が異なります...
目次簡単な紹介間隔の設定説明するパラメータ戻り値使用法タイムアウトの設定説明するパラメータ使用法:タ...
問題: MySQL がデータ ファイルを保存するパーティションの容量が小さく、現在いっぱいになってい...
webpack をパッケージ化する前に、次の作業が完了していることを確認する必要があります。 1) ...
通常、CSS セレクターは上から下に選択し、親要素を介して子要素を選択します。では、子要素を介して親...
MySQLの古いバージョンをアンインストールします(古いバージョンがない場合は、この手順をスキップし...
目次インストールパッケージのダウンロードインストール環境変数の設定インストールが成功したか確認する記...