ユニークインデックスの S ロックと X ロックによる MySQL デッドロック ルーチンの理解

ユニークインデックスの S ロックと X ロックによる MySQL デッドロック ルーチンの理解

「初心者向けソースコードからの MySQL デッドロック問題の理解」では、MySQL ソースコードをデバッグしてデッドロックを確認するプロセスを紹介しました。この記事では、一般的なケースについて説明します。
今回はユニークインデックスのSロックとXロックの愛憎関係についてお話します。

簡単な例を見てみましょう

# データの構築 CREATE TABLE `t1` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `名前` varchar(10),
 `レベル` int(11)、
 主キー (`id`)、
 ユニークキー `uk_name` (`name`)
);
`t1` (`name`, `level`) に VALUES ('A',0) を挿入します。

# 問題のある SQL ステートメントは次のとおりです。同時実行時にデッドロックが発生します。INSERT ignore INTO `t1` (`name`, `level`) VALUES ('A',0);
t1 を更新し、level = 1 を設定します。name = "A" です。

前に紹介したソースコード分析方法を使用して、まずこれら 2 つのステートメントにどのようなロックが追加されているかを確認し、次にデッドロックの形成プロセスを分析します。

最初の声明

INSERT ignore INTO t1 (名前、レベル) VALUES ('A',0);

デバッグ中に得られた結果は次のとおりです。

このステートメントにより、一意のキー uk_name に共有ロック (S ロック) が追加され、成功していることがわかります。

2番目の声明

t1 を更新し、level = 1 を設定します。name = "A" です。

一意のキーによってデータベース フィールドを更新します。

この状況は前回の記事で紹介しました。ユニーク インデックスに X ロックが追加され、次に主キー インデックスに X ロックが追加されます。

この方法では、デッドロックの問題を非常に簡単に再現できます。手順は次のとおりです。

1. 2つのセッションを開き、開始する
2.セッション1はINSERT ignore INTO t1 (name, level) VALUES ('A',0);を実行します。
3.セッション2はINSERT ignore INTO t1 (name, level) VALUES ('A',0);を実行します。
4.セッション1はupdate t1 set level = 1 where name = "A";を実行し、待機状態に入ります。
5. セッション2はupdate t1 set level = 1 where name = "A";を実行すると、デッドロックが発生してロールバックされますが、トランザクション1は正常に実行されます。

詳細なロックステータスの変更は次のとおりです。

t1 t2述べる
挿入無視- t1はukDB_SUCCESSのSロックを正常に取得しました。
-挿入無視t2はukDB_SUCCESSのSロックを正常に取得しました。
アップデート- t1はukのXロックを取得しようとしますが、失敗し、待機状態DB_LOCK_WAITになります。
-アップデートt2はukのXロックを取得しようとしてデッドロックを発見し、DB_DEADLOCKを生成します。
-デッドロックt2 Sロックを解除
成功- -

デッドロックログは次のとおりです。

最近検出されたデッドロック
------------------------
181208 23:00:52
*** (1)取引:
トランザクション 53A7、アクティブ 162 秒 開始インデックス読み取り
使用中の MySQL テーブル 1、ロックされているテーブル 1
LOCK WAIT 3 つのロック構造体、ヒープ サイズ 376、2 つの行ロック
MySQL スレッド ID 12、OS スレッド ハンドル 0x700010522000、クエリ ID 1424 localhost root 更新中
t1 を更新し、レベルを 1 に設定し、名前を "A" にします。
*** (1) このロックが許可されるのを待機しています:
レコード ロック スペース ID 89 ページ番号 4 n ビット 72 テーブル `lock_demo2`.`t1` のインデックス `uk_name` trx ID 53A7 lock_mode X はレコードをロックしますが、ギャップ待機はロックしません
レコード ロック、ヒープ番号 2 物理レコード: n_fields 2; コンパクト フォーマット; 情報ビット 0
 0: 長さ 1; 16 進数 41; 昇順 A;;
 1: 長さ 4; 16 進数 80000001; 昇順 ;;

*** (2)取引:
トランザクション 53A8、アクティブ 8 秒開始インデックス読み取り
使用中の MySQL テーブル 1、ロックされているテーブル 1
3 つのロック構造体、ヒープ サイズ 376、2 つの行ロック
MySQL スレッド ID 96、OS スレッド ハンドル 0x70001062e000、クエリ ID 1425 localhost root 更新中
t1 を更新し、レベルを 1 に設定し、名前を "A" にします。
*** (2) ロックを保持する:
レコード ロック スペース ID 89 ページ番号 4 n ビット 72 テーブル `lock_demo2`.`t1` のインデックス `uk_name` トランザクション ID 53A8 ロック モード S
レコード ロック、ヒープ番号 2 物理レコード: n_fields 2; コンパクト フォーマット; 情報ビット 0
 0: 長さ 1; 16 進数 41; 昇順 A;;
 1: 長さ 4; 16 進数 80000001; 昇順 ;;

*** (2) このロックが許可されるのを待機しています:
レコード ロック スペース ID 89 ページ番号 4 n ビット 72 テーブル `lock_demo2`.`t1` のインデックス `uk_name` trx ID 53A8 lock_mode X はレコードをロックしますが、ギャップ待機はロックしません
レコード ロック、ヒープ番号 2 物理レコード: n_fields 2; コンパクト フォーマット; 情報ビット 0
 0: 長さ 1; 16 進数 41; 昇順 A;;
 1: 長さ 4; 16 進数 80000001; 昇順 ;;

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

このデッドロックログを詳しく見てみましょう

*** (1) このロックが許可されるのを待機しています:
レコード ロック スペース ID 89 ページ番号 4 n ビット 72 インデックス uk_name of table lock_demo2.t1 trx ID 53A7 lock_mode X はレコードをロックしますが、ギャップ待機はロックしません

トランザクション1は、ユニークインデックスuk_nameのXロック(非ギャップロックレコードロック)を取得したい。

*** (2) ロックを保持する:
レコード ロック スペース ID 89 ページ番号 4 n ビット 72 インデックス uk_name of table lock_demo2.t1 trx ID 53A8 ロック モード S

トランザクション2は、ユニークインデックスuk_nameにSロック(共有ロック)を保持します。

*** (2) このロックが許可されるのを待機しています:
レコード ロック スペース ID 89 ページ番号 4 n ビット 72 インデックス uk_name of table lock_demo2.t1 trx ID 53A8 lock_mode X はレコードをロックしますが、ギャップ待機はロックしません

トランザクション 2 は、uk_name 一意インデックスの X ロック (非ギャップ ロック レコード ロック) を取得しようとしています。
これは以前の理論的結論と一致しています。

以上がこの記事の全内容です。皆様の勉強のお役に立てれば幸いです。また、123WORDPRESS.COM を応援していただければ幸いです。

以下もご興味があるかもしれません:
  • 異なるインデックスを更新してMySQLのデッドロックルーチンを解決する
  • MySQL デッドロック シナリオ例の分析
  • MySQL (InnoDB) がデッドロックを処理する方法の詳細な説明
  • MySQL における楽観的ロックと悲観的ロックの例
  • Mysqlは実行中のトランザクションを照会し、ロックを待機する方法
  • MySQLの関連ロックについての簡単な理解

<<:  Zabbix を使用して Nginx/Tomcat/MySQL を監視する方法の詳細なチュートリアル

>>:  vuex の補助関数 mapGetters の基本的な使い方の詳細な説明

推薦する

HTMLウェブページテーブル構造化マークアップの応用に関する簡単な説明

Web テーブルの構造マークアップについて説明する前に、いくつかの画像を見てみましょう。 HTML ...

SpringBoot + Vue プロジェクトを Linux サーバーにデプロイするための詳細なチュートリアル

序文SpringBoot + Vueのフロントエンドとバックエンドを分離したプロジェクトをどのように...

MySQL 8.0.12 のインストールと使用方法のチュートリアル

MySQL 8.0.12のインストールと使用のチュートリアルを録画しました。ウィンドウズまず、公式ウ...

Dockerデータのバックアップとリカバリプロセスの詳細な説明

データのバックアップ操作は非常に簡単です。次のコマンドを実行します。 docker run --vo...

Web プロジェクト開発 JS 機能の手ぶれ補正とスロットリングのサンプル コード

目次安定導入手ぶれ補正シーン1(マウスの動き込み)手ぶれ補正シーン2(キーボードのキー)関数のスロッ...

バックエンドデータを取得するためのVue Elementフロントエンドアプリケーション開発

目次概要1. バックエンドデータの取得と処理2. インターフェース表示処理概要前回のエッセイ「ステッ...

MySQL マルチテーブル結合クエリ例の説明

実際のプロジェクトでは、複数のテーブル間に関係が存在します。 1 つのテーブル内のすべてのデータを取...

Nginxのアクセスボリューム制御の詳細な説明

目的リクエスト アクセス ボリュームを制御するための Nginx ngx_http_limit_co...

負の距離(共感) - 相互影響の反復プロセス

ネガティブな距離は共感を意味します。序文(疑問の提起):プロダクトマネージャーは機能を把握します。機...

Chrome をクラッシュさせる CSS コードの行

一般的な CSS コードでは、UI レイアウトや互換性に関して軽微な問題が発生するだけです。しかし、...

Linux での tcpdump コマンド例の詳細な説明

序文簡単に言えば、tcpdump は、ネットワーク上のトラフィックをダンプし、ユーザーの定義に従って...

innerHTML を理解する

<br />関連記事: innerHTML HTML DOM insertRow() メ...

モバイルデバイスでのフリーズ問題に対する CSS3 ソリューション (アニメーション パフォーマンスの最適化)

1. CSS、jQuery、Canvasを使用してアニメーションを作成する1. キャンバス利点: ...

WebページのレイアウトではIE6の互換性の問題を考慮する必要があります

下の図は、当社のウェブサイト統計システムの訪問者詳細におけるブラウザ閲覧率を示しており、IE6 が ...

この記事では、6つの負荷分散技術の実装方法をまとめます(要約)

ロード バランシングは、サーバー クラスタの展開でよく使用されるデバイスです。マシンのパフォーマンス...