MySQL デッドロック ルーチン: 一意のインデックスの下でのバッチ挿入順序の不一致

MySQL デッドロック ルーチン: 一意のインデックスの下でのバッチ挿入順序の不一致

序文

デッドロックの本質はリソースの競合です。バッチ挿入の順序が一貫していないと、デッドロックに陥りやすくなります。この状況を分析してみましょう。デモンストレーションの便宜上、バッチ挿入は複数挿入として書き換えられます。

まずは小さな実験をいくつかやってみましょう。簡略化されたテーブル構造は次のようになります。

テーブル `t1` を作成します (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `a` varchar(5)、
 `b` varchar(5)、
 主キー (`id`)、
 ユニークキー `uk_name` (`a`,`b`)
);

実験1:

レコードが存在しない場合に、同じ順序の 2 つのバッチ挿入が同時に実行されると、2 番目のバッチ挿入はロック待機状態になります。

t1 t2
始める;始める;
ignore を t1(a, b)values("1", "1") に挿入します。成功
ignore を t1(a, b)values("1", "1") に挿入します。ロック待機状態

現在のロック状態を確認できます

mysql> information_schema.innodb_locks から * を選択します。
+-------------+--------------+-------------+-------------+-------------+-------------+------------+------------+------------+------------+
| lock_id | lock_trx_id | lock_mode | lock_type | lock_table | lock_index | lock_space | lock_page | lock_rec | lock_data |
+-------------+--------------+-------------+-------------+-------------+-------------+------------+------------+------------+------------+
| 31AE:54:4:2 | 31AE | S | レコード | `d1`.`t1` | `uk_name` | 54 | 4 | 2 | '1', '1' |
| 31AD:54:4:2 | 31AD | X | レコード | `d1`.`t1` | `uk_name` | 54 | 4 | 2 | '1', '1' |
+-------------+--------------+-------------+-------------+-------------+-------------+------------+------------+------------+------------+

トランザクション t1 の挿入を実行すると、ロック ブレークポイントは表示されません。これは、MySQL 挿入の原理に関連しています。

挿入により暗黙的なロックが追加されます。暗黙のロックとは何ですか?暗黙のロックはロックがないことを意味する

t1 でレコードを挿入する場合、ロックは適用されません。この時点では、トランザクション t1 はまだコミットされていません。トランザクション t2 が挿入を試みると、このレコードが見つかります。t2 は S ロックを取得しようとし、レコードのトランザクション ID がアクティブかどうかを判断します。アクティブであれば、トランザクションが終了していないことを意味します。これにより、t1 は暗黙的なロックを明示的なロック (X ロック) にアップグレードできます。

ソースコードは以下のとおりです

t2 Sロック取得結果: DB_LOCK_WAIT

実験2:

一貫性のないバッチ挿入順序によるデッドロック

t1 t2
始める
t1(a, b)values("1", "1")に挿入します。成功
t1(a, b)values("2", "2")に挿入します。成功
t1(a, b)values("2", "2")に挿入します。 t1はSロックを取得しようとし、t2の暗黙のロックを明示的なXロックにアップグレードし、DB_LOCK_WAITに入ります。
t1(a, b)values("1", "1")に挿入します。 t2 は S ロックを取得しようとしますが、これにより t1 の暗黙的なロックが明示的な X ロックにアップグレードされ、デッドロックが発生します。
------------------------
最近検出されたデッドロック
------------------------
181101 9:48:36
*** (1)取引:
トランザクション 3309、アクティブ 215 秒挿入
使用中の MySQL テーブル 1、ロックされているテーブル 1
LOCK WAIT 3 ロック構造体、ヒープ サイズ 376、2 行ロック、UNDO ログ エントリ 2
MySQL スレッド ID 2、OS スレッド ハンドル 0x70000a845000、クエリ ID 58 localhost ルート更新
t1(a, b)values("2", "2") に挿入
*** (1) このロックが許可されるのを待機しています:
レコード ロック スペース ID 55 ページ番号 4 n ビット 72 テーブル `d1`.`t1` のインデックス `uk_name` トランザクション ID 3309 ロック モード S 待機中
レコード ロック、ヒープ番号 3 物理レコード: n_fields 3; コンパクト フォーマット; 情報ビット 0
 0: 長さ 1; 16 進数 32; 昇順 2;;
 1: 長さ 1; 16 進数 32; 昇順 2;;
 2: 長さ 4; 16 進数 80000002; 昇順 ;;

*** (2)取引:
トランザクション 330A、アクティブ 163 秒挿入
使用中の MySQL テーブル 1、ロックされているテーブル 1
3 つのロック構造体、ヒープ サイズ 376、2 つの行ロック、UNDO ログ エントリ 2
MySQL スレッド ID 3、OS スレッド ハンドル 0x70000a888000、クエリ ID 59 localhost ルート更新
t1(a, b)values("1", "1") に挿入
*** (2) ロックを保持する:
レコード ロック スペース ID 55 ページ番号 4 n ビット 72 テーブル `d1`.`t1` のインデックス `uk_name` trx ID 330A lock_mode X はレコードをロックしますが、ギャップはロックしません
レコード ロック、ヒープ番号 3 物理レコード: n_fields 3; コンパクト フォーマット; 情報ビット 0
 0: 長さ 1; 16 進数 32; 昇順 2;;
 1: 長さ 1; 16 進数 32; 昇順 2;;
 2: 長さ 4; 16 進数 80000002; 昇順 ;;

*** (2) このロックが許可されるのを待機しています:
レコード ロック スペース ID 55 ページ番号 4 n ビット 72 テーブル `d1`.`t1` のインデックス `uk_name` トランザクション ID 330A ロック モード S 待機中
レコード ロック、ヒープ番号 2 物理レコード: n_fields 3; コンパクト フォーマット; 情報ビット 0
 0: 長さ 1; 16 進数 31; 昇順 1;;
 1: 長さ 1; 16 進数 31; 昇順 1;;
 2: 長さ 4; 16 進数 80000001; 昇順 ;;

*** トランザクションをロールバックします (2)

このような問題をどうやって解決するのでしょうか?

考えられる解決策の 1 つは、アプリケーション層でソートした後にデータを挿入することです。

要約する

以上がこの記事の全内容です。この記事の内容が皆様の勉強や仕事に何らかの参考学習価値をもたらすことを願います。123WORDPRESS.COM をご愛顧いただき、誠にありがとうございます。

以下もご興味があるかもしれません:
  • Mysql のデッドロックの表示とデッドロックの除去の詳細な説明
  • MySQLのデッドロックチェック処理の通常の方法
  • MySQLデッドロックの原因と解決策
  • MySQLデッドロック問題の詳細な分析
  • MySQL デッドロック シナリオ例の分析
  • 魔法のMySQLデッドロックトラブルシューティング記録
  • MySQL データベースのパージデッドロック問題の分析
  • SQLによる分散デッドロックの検出と排除の詳細な説明

<<:  uniapp パッケージ化されたアプレット レーダー チャート コンポーネントの完全なコード

>>:  Dockerプライベートウェアハウスの構築とインターフェース管理の詳細な説明

推薦する

Vue+SpringBoot+Shiroのクロスドメイン問題を解決する

目次1. Vueフロントエンドを構成する1. クロスドメイン構成を開発する2. 本番環境のクロスドメ...

ドラッグアンドドロップでVueユーザーインターフェースを生成する方法

目次序文1. 技術原理1.1 レイアウト1.2 コンポーネント1.3 ステータス1.4 イベント1....

MySql5.x を MySql8.x にアップグレードする方法と手順

MySQL 5.x と MySQL 8.0.X のいくつかの違いapplication.proper...

さまざまな Tomcat ログと catalina.out ファイルのセグメンテーションの関係についての簡単な分析

Tomcatログの関係一枚の写真は千の言葉に値する! localhost.{yyyy-MM-dd}....

進捗バー効果を実現するJavaScript

この記事では、プログレスバー効果を実現するためのJavaScriptの具体的なコードを参考までに紹介...

HTML スペースコードの簡単な分析

HTML についてどれくらい知っていますか? 現在、基本的な HTML コードを学習している場合は、...

JSネイティブ2列シャトル選択ボックスの実装例

目次いつ使うか構造的ブランチコードいつ使うか選択動作を完了するには、2 つの列間で要素を直感的に移動...

Dockerを使用してMySQLデータベースをインストールするDeepinの詳細な説明

まずMySQLソースをクエリするdocker 検索 mysql公式ウェブサイトにアクセスしてイメージ...

MySQL Community Server 5.6.39 のインストール方法

この記事では、MySQLのダウンロードとインストールの詳細なチュートリアルを記載しています。具体的な...

Vue で HTML 5 ドラッグ アンド ドロップ API を使用する方法

ドラッグ アンド ドロップ API は、ドラッグ可能な要素を HTML に追加し、ドラッグ可能な豊富...

テーブルの作成、フィールドの追加、フィールドの変更、インデックスの追加によく使用される MySQL の SQL 文の概要

この記事では、テーブルの作成、フィールドの追加、フィールドの変更、インデックスの追加を行う一般的な ...

Tomcatの各ポートの機能の詳細な説明

tomcat 設定ファイルから、tomcat の起動時にデフォルトで 8080 (8443)、800...

nginx 設定ファイルパスとリソースファイルパスを表示する方法

nginx 設定ファイルのパスを表示する nginx -t 経由nginx -t コマンドの本来の機...

React構成サブルーティングの実装

1. コンポーネント First.js にはサブコンポーネントがあります。 './Admin...

MySQL で MHA アーキテクチャのデプロイメントを構築する手順

目次マハ1. MAHアーキテクチャの概要2. 適用可能なシナリオ3. MHAの動作原理4. MHAの...