検索
ホームページデータベースmysql チュートリアルMySQL 最適化インデックスのマージによって発生するデッドロックを解決する方法

背景

本番環境でデッドロックが発生しました。デッドロックのログを確認すると、デッドロックの原因は 2 つの同一の更新ステートメント (where 条件の値のみが異なる) であることがわかりました。

は次のとおりです:

UPDATE test_table SET `status` = 1 WHERE `trans_id` = 'xxx1' AND `status` = 0;
UPDATE test_table SET `status` = 1 WHERE `trans_id` = 'xxx2' AND `status` = 0;

最初は理解するのが難しかったですが、多くの調査と研究を経て、デッドロック形成の具体的な原理を分析しました。同じ問題を抱えている友人たちに役立つことを願って、この記事をみんなと共有したいと思います。

MySQL には多くの知識ポイントがあるため、多くの名詞はここではあまり紹介しません。興味のある友人は、特別に詳しく学習してフォローしてください。

デッドロック ログ

*** (1) TRANSACTION:
TRANSACTION 791913819, ACTIVE 0 sec starting index read, thread declared inside InnoDB 4999
mysql tables in use 3, locked 3
LOCK WAIT 4 lock struct(s), heap size 1184, 3 row lock(s)
MySQL thread id 462005230, OS thread handle 0x7f55d5da3700, query id 2621313306 x.x.x.x test_user Searching rows for update
UPDATE test_table SET `status` = 1 WHERE `trans_id` = 'xxx1' AND `status` = 0;
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 110 page no 39167 n bits 1056 index `idx_status` of table `test`.`test_table` trx id 791913819 lock_mode X waiting
Record lock, heap no 495 PHYSICAL RECORD: n_fields 2; compact format; info bits 0

*** (2) TRANSACTION:
TRANSACTION 791913818, ACTIVE 0 sec starting index read, thread declared inside InnoDB 4999
mysql tables in use 3, locked 3
5 lock struct(s), heap size 1184, 4 row lock(s)
MySQL thread id 462005231, OS thread handle 0x7f55cee63700, query id 2621313305 x.x.x.x test_user Searching rows for update
UPDATE test_table SET `status` = 1 WHERE `trans_id` = 'xxx2' AND `status` = 0;
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 110 page no 39167 n bits 1056 index `idx_status` of table `test`.`test_table` trx id 791913818 lock_mode X
Record lock, heap no 495 PHYSICAL RECORD: n_fields 2; compact format; info bits 0

*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 110 page no 41569 n bits 88 index `PRIMARY` of table `test`.`test_table` trx id 791913818 lock_mode X locks rec but not gap waiting
Record lock, heap no 14 PHYSICAL RECORD: n_fields 30; compact format; info bits 0

*** WE ROLL BACK TRANSACTION (1)

上記のデッドロック ログを簡単に分析します:

  • 1. 最初の内容 (行 1 ~ 9) )、行 6 はトランザクション (1) によって実行される SQL ステートメントで、行 7 と 8 はトランザクション (1) が idx_status インデックスの X ロックを待機していることを意味します;

  • 2。コンテンツの 2 番目のブロック (11 行目から 19 行目) では、16 行目はトランザクション (2) によって実行される SQL ステートメントであり、17 行目と 18 行目は、トランザクション (2) が idx_status インデックス X ロック オンを保持していることを意味します。

  • 意味: トランザクション (2) は、PRIMARY インデックスの X ロックの取得を待機しています。 (ただし、ギャップではないということは、ギャップ ロックではないことを意味します)
  • 4. 最後の文は、MySQL がトランザクション (1) をロールバックしたことを意味します。
  • テーブル構造
CREATE TABLE `test_table` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`trans_id` varchar(21) NOT NULL,
`status` int(11) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `uniq_trans_id` (`trans_id`) USING BTREE,
KEY `idx_status` (`status`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8

テーブル構造からわかるように、

trans_id

columnuniq_trans_id # に一意のインデックスがあります。 ##,status idx_status には通常のインデックスがあり、id 列は主キー インデックス PRIMARY です。 InnoDB エンジンには 2 種類のインデックスがあります:

    クラスター化インデックス:
  • データ ストレージとインデックスを配置します。インデックス構造のリーフ ノードは一緒に行データを格納します。

  • 補助インデックス:
  • 補助インデックスのリーフ ノードには、クラスター化インデックスのキー値である主キー値が格納されます。

    主キー インデックス
  • PRIMARY
はクラスター化インデックスであり、行データはリーフ ノードに格納されます。

uniq_trans_id インデックスと idx_status インデックスは補助インデックスであり、リーフ ノードには主キー値 (id 列の値) が格納されます。 補助インデックスを通じて行データを検索する場合、最初に補助インデックスを通じて主キー ID を見つけ、次に主キー インデックスを通じて二次検索 (これもテーブルに呼び出されます) を実行し、最後に行データを見つけます。

実行計画

実行計画を見ると、update ステートメントでインデックスのマージが使用されていることがわかります。つまり、このステートメントでは ## の両方が使用されています。 #uniq_trans_id MySQL 最適化インデックスのマージによって発生するデッドロックを解決する方法 インデックスが再度使用されます

idx_status

インデックス、 intersect(uniq_trans_id,idx_status) を使用することは、2 つのインデックスを通じて交差を取得することを意味します。 index_merge が使用される理由 MySQL5.0 より前は、テーブルは一度に 1 つのインデックスしか使用できず、条件付きスキャンで複数のインデックスを同時に使用することはできませんでした。ただし、5.1 からは、

index merge

最適化テクノロジが導入され、複数のインデックスを使用して同じテーブルで条件付きスキャンを実行できるようになりました。

たとえば、実行プラン内のステートメント:

UPDATE test_table SET `status` = 1 WHERE `trans_id` = '38' AND `status` = 0 ;

MySQL は、条件 trans_id = ‘38’ に基づいて uniq_trans_id# を使用します。

## インデックスはリーフ ノードに保存されている ID 値を検索します。同時に、条件

status = 0 に従って、idx_status インデックスを使用して、リーフ ノードに保存された ID 値; その後、2 つのグループ ID 値が交差され、最終的に交差 ID がテーブルに返されます、つまり、リーフ ノードに保存された行データが PRIMARY インデックスを通じて検出されます。 多くの人がここで疑問を抱くかもしれません。uniq_trans_id はすでに一意のインデックスです。このインデックスを通じて見つかるのは最大でも 1 つのデータだけです。では、なぜ MySQL オプティマイザーは 2 つのインデックスを使用するのでしょうか。 2 つのインデックスの共通部分を検索し、クエリのためにテーブルに戻ります。これにより、別の idx_status

インデックス検索プロセスが追加されませんか?これら 2 つの状況の実行プロセスを分析してみましょう。

最初の例では、uniq_trans_id インデックスのみを使用します。

##クエリ条件 trans_id = ‘38’ によると、 use

uniq_trans_id
    インデックスはリーフ ノードに保存されている ID 値を検索します;
  • PRIMARY インデックスを使用して、見つかった ID 値を通じてリーフ ノードに保存されている行データを検索します;

  • 次に、見つかった行データを
  • status = 0

    条件でフィルター処理します。

  • 2 番目のタイプはインデックスのマージを使用します。 Using intersect(uniq_trans_id,idx_status)

trans_id によると= ‘38’ クエリ条件、

uniq_trans_id
    インデックスを使用して、リーフ ノードに保存されている ID 値を検索します;
  • status によると = 0 クエリ条件。

    idx_status
  • インデックスを使用して、リーフ ノードに保存されている ID 値を検索します。
  • 1/2 で見つかった ID 値の共通部分を取得し、PRIMARY インデックスを使用してリーフ ノードに保存されている行データを見つけます

上記の 2 つのケースの主な違いは、1 つ目の方法では最初にインデックスを通じてデータを検索し、次に他のクエリ条件を使用してフィルタリングすること、2 つ目の方法では最初に ID 値の共通部分を取得することです。 2 つのインデックスを通じて見つかりました。交差部分の後に ID 値がまだある場合は、テーブルに戻ってデータを取得します。

オプティマイザが 2 番目のケースの実行コストが最初のケースの実行コストより小さいと判断した場合、インデックスのマージが発生します。 (運用環境のフロー テーブルには status = 0 のデータがほとんどありません。これが、オプティマイザが 2 番目のケースを考慮する理由の 1 つです)。

index_merge

MySQL 最適化インデックスのマージによって発生するデッドロックを解決する方法

index_merge を使用した後にデッドロックが発生する理由 上記は、2 つの更新トランザクションをロックするプロセスを簡単に示しています。図では、idx_status

インデックスと PRIMARY (クラスター化インデックス) の両方に重複部分と交差部分があり、デッドロックの状態が発生します。

たとえば、次のようなタイミングでデッドロックが発生します。

MySQL 最適化インデックスのマージによって発生するデッドロックを解決する方法

トランザクション 1 がトランザクション 2 の解放を待つ。ロックが解除されている場合、トランザクション 2 はトランザクション 1 がロックを解放するのを待つため、デッドロックが発生します。

MySQL はデッドロックを検出すると、より低いコストでトランザクションを自動的にロールバックします。上のタイミング図のように、トランザクション 1 がトランザクション 2 よりも少ないロックを保持している場合、MySQL はトランザクション 1 を続行します。 。

解決策

1. コード レベル
  • # クエリ条件から、データをクエリするために trans_id

    のみを渡します。 、コード レベルでステータスが 0 であるかどうかを判断します。
  • Use force Index(uniq_trans_id) クエリ ステートメントで uniq_trans_id

    を使用するように強制します。 index;
  • ここで、クエリ条件の直後に id フィールドを使用し、主キーを介して更新します。

2.
    idx_status
  • インデックスを MySQL レベルから削除するか、これら 2 つの列を含む結合インデックスを作成します。

    ##MySQL オプティマイザーの

    index merge
  • 最適化をオフにします。

以上がMySQL 最適化インデックスのマージによって発生するデッドロックを解決する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明
この記事は亿速云で複製されています。侵害がある場合は、admin@php.cn までご連絡ください。
MySQLの役割:WebアプリケーションのデータベースMySQLの役割:WebアプリケーションのデータベースApr 17, 2025 am 12:23 AM

WebアプリケーションにおけるMySQLの主な役割は、データを保存および管理することです。 1.MYSQLは、ユーザー情報、製品カタログ、トランザクションレコード、その他のデータを効率的に処理します。 2。SQLクエリを介して、開発者はデータベースから情報を抽出して動的なコンテンツを生成できます。 3.MYSQLは、クライアントサーバーモデルに基づいて機能し、許容可能なクエリ速度を確保します。

MySQL:最初のデータベースを構築しますMySQL:最初のデータベースを構築しますApr 17, 2025 am 12:22 AM

MySQLデータベースを構築する手順には次のものがあります。1。データベースとテーブルの作成、2。データの挿入、および3。クエリを実行します。まず、createdAtabaseおよびcreateTableステートメントを使用してデータベースとテーブルを作成し、InsertINTOステートメントを使用してデータを挿入し、最後にSelectステートメントを使用してデータを照会します。

MySQL:データストレージに対する初心者向けのアプローチMySQL:データストレージに対する初心者向けのアプローチApr 17, 2025 am 12:21 AM

MySQLは、使いやすく強力であるため、初心者に適しています。 1.MYSQLはリレーショナルデータベースであり、CRUD操作にSQLを使用します。 2。インストールは簡単で、ルートユーザーのパスワードを構成する必要があります。 3.挿入、更新、削除、および選択してデータ操作を実行します。 4. Orderby、Where and Joinは複雑なクエリに使用できます。 5.デバッグでは、構文をチェックし、説明を使用してクエリを分析する必要があります。 6.最適化の提案には、インデックスの使用、適切なデータ型の選択、優れたプログラミング習慣が含まれます。

MySQLは初心者に優しいですか?学習曲線の評価MySQLは初心者に優しいですか?学習曲線の評価Apr 17, 2025 am 12:19 AM

MySQLは初心者に適しています。1)インストールと構成、2)リッチラーニングリソース、3)直感的なSQL構文、4)強力なツールサポート。それにもかかわらず、初心者はデータベースの設計、クエリの最適化、セキュリティ管理、データのバックアップなどの課題を克服する必要があります。

SQLはプログラミング言語ですか?用語を明確にするSQLはプログラミング言語ですか?用語を明確にするApr 17, 2025 am 12:17 AM

はい、sqlisaprogramginglanguagespecializedfordatamanamanagement.1)それはdeclarative、focusingonwhattoachieveratherthanhow.2)

酸性の特性(原子性、一貫性、分離、耐久性)を説明します。酸性の特性(原子性、一貫性、分離、耐久性)を説明します。Apr 16, 2025 am 12:20 AM

酸性属性には、原子性、一貫性、分離、耐久性が含まれ、データベース設計の基礎です。 1.原子性は、トランザクションが完全に成功するか、完全に失敗することを保証します。 2.一貫性により、データベースがトランザクションの前後に一貫性を保証します。 3.分離により、トランザクションが互いに干渉しないようにします。 4.永続性により、トランザクションの提出後にデータが永久に保存されることが保証されます。

MySQL:データベース管理システムとプログラミング言語MySQL:データベース管理システムとプログラミング言語Apr 16, 2025 am 12:19 AM

MySQLは、データベース管理システム(DBMS)であるだけでなく、プログラミング言語にも密接に関連しています。 1)DBMSとして、MySQLはデータを保存、整理、取得するために使用され、インデックスを最適化するとクエリのパフォーマンスが向上する可能性があります。 2)SQLとPythonに埋め込まれたプログラミング言語とSQLalchemyなどのORMツールを使用すると、操作を簡素化できます。 3)パフォーマンスの最適化には、インデックス、クエリ、キャッシュ、ライブラリ、テーブル分割、およびトランザクション管理が含まれます。

MySQL:SQLコマンドでデータの管理MySQL:SQLコマンドでデータの管理Apr 16, 2025 am 12:19 AM

MySQLはSQLコマンドを使用してデータを管理します。 1.基本コマンドには、select、挿入、更新、削除が含まれます。 2。高度な使用には、参加、サブクエリ、および集計関数が含まれます。 3.一般的なエラーには、構文、ロジック、パフォーマンスの問題が含まれます。 4。最適化のヒントには、インデックスの使用、Select*の回避、制限の使用が含まれます。

See all articles

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

強力な PHP 統合開発環境

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

EditPlus 中国語クラック版

EditPlus 中国語クラック版

サイズが小さく、構文の強調表示、コード プロンプト機能はサポートされていません

Safe Exam Browser

Safe Exam Browser

Safe Exam Browser は、オンライン試験を安全に受験するための安全なブラウザ環境です。このソフトウェアは、あらゆるコンピュータを安全なワークステーションに変えます。あらゆるユーティリティへのアクセスを制御し、学生が無許可のリソースを使用するのを防ぎます。

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール