MySQL のロックロックは、並行環境におけるリソースの競合を解決する手段です。その中でも、楽観的並行性制御、悲観的並行性制御、マルチバージョン並行性制御は、データベースの並行性制御に使用される主な技術的手段です(詳細は前回の記事を参照)。MySQL のロックは、悲観的並行性制御です。 MySQL には多くの種類のロックがあり、次のように分類できます。 読み書きによってデータベースの読み取りと書き込みの観点から、データベース ロックは次のカテゴリに分類できます。
互換性マトリックスは以下のとおりです(+は互換性あり、-は互換性なしを表します)
粒度別MySQL はさまざまなレベルのロックをサポートしており、ロックされたデータの範囲も異なります。これは、ロックの粒度と呼ばれるものです。 MySQL には、行レベル ロック、ページレベル ロック、テーブルレベル ロックの 3 つのロック レベルがあります。異なるストレージ エンジンは、異なるロック粒度をサポートします。たとえば、MyISAM および MEMORY ストレージ エンジンはテーブル レベルのロックを使用し、ページ レベルのロックは BDB ストレージ エンジンでのみサポートされ、InnoDB ストレージ エンジンは行レベルのロックとテーブル レベルのロックをサポートします。デフォルトでは行レベルのロックが使用されます。 特徴 テーブル レベルのロック: オーバーヘッドが低く、ロックが高速で、デッドロックがなく、ロックの粒度が大きく、ロック競合の可能性が最も高く、同時実行性が最も低い。データベース エンジンは、必要なすべてのロックを常に一度に取得し、テーブル ロックを常に同じ順序で取得することで、デッドロックを回避します。 以下では、行ロックとテーブル ロックについて詳しく説明します。ページ ロックはほとんど使用されないため、ここでは説明しません。 行ロック行ごとにデータをロックします。 InnoDB の行ロックは、インデックス上のインデックス項目をロックすることによって実装されます。InnoDB にはクラスター化インデックスが必要であり、行ロックは最終的にクラスター化インデックスに適用されます。非クラスター化インデックスを介してクエリを実行する場合、最初に非クラスター化インデックスがロックされ、次にクラスター化インデックスがロックされます。 where ステートメントにクラスター化インデックスとセカンダリ インデックスの両方が含まれている場合、クラスター化インデックスが最初にロックされ、次にセカンダリ インデックスがロックされます。ロックは段階的に行われるため、デッドロックが発生する可能性があります。 MySQL の行ロックは、S ロックと X ロックをさらに正確に細分化することで、行ロックの粒度を細かくし、競合を減らします。これが「精密モード」と呼ばれる互換性マトリックスです。 (このマトリックスは公式ドキュメントには記載されていませんが、MySQL lock0lock.c:lock_rec_has_to_wait ソース コードから推測されたものです。) 行ロック互換性マトリックス
S ロックと S ロックは完全に互換性があるため、互換性を判断する際に正確なモードを比較する必要はありません。 S,X と X,X 間で使用される正確なモード検出。このマトリックスからはいくつかの特徴がわかります。
注記
テーブルロックとテーブルのロックに関する誤解InnoDB は、インデックス条件を通じてデータが正しく取得された (インデックス障害がない) 場合にのみ行レベルのロックを使用します。それ以外の場合、InnoDB はテーブル内のすべてのレコードをロックします。つまり、テーブル全体をロックします。ここではテーブル全体のロックについて説明していますが、Innodb はテーブルをロックするためにテーブル ロックを使用しないことに注意してください。代わりに、以下で紹介する Next-Key Lock を使用してテーブル全体をロックします。インターネット上の多くの記述では、テーブル ロックを使用する必要があると書かれていますが、実際にはそうではありません。次の例からこのことがわかります。 次のデータ (MySQL8) があると仮定します。 mysql> ユーザーから * を選択します。 +----+------+-----+ | ID | 名前 | 年齢 | +----+------+-----+ | 1 | 1 | | 2 | 1 | | 3 | 1 | | 4 | 1 | | 5 | 1 | +----+------+-----+ 方法1: テーブルロックを使用してテーブルをロックし、エンジンの状態を確認します mysql> 開始します。 クエリは正常、影響を受けた行は 0 行 (0.00 秒) mysql> ユーザーが書き込むテーブルをロックします。 クエリは正常、影響を受けた行は 0 行 (0.00 秒) mysql> エンジン innodb ステータスを表示\G ... ------------ 取引 ------------ Trx ID カウンター 4863 トランザクションの n:o < 4862 のパージが完了しました。n:o < 0 の状態を元に戻します: 実行中ですがアイドル状態です 履歴リストの長さ 911 各セッションのトランザクションのリスト: ---トランザクション 281479760456232、開始されていません 使用中の mysql テーブル 1、ロックされている 1 ################## ロック構造体 0、ヒープ サイズ 1136、行ロック 0 であることに注意してください ... 次に、インデックスされていないフィールドをクエリしてロックし、エンジンのステータスを確認します。 ## 最後のテーブルのロックを解除します。 lock firstmysql> unlock tables; クエリは正常、影響を受けた行は 0 行 (0.00 秒) mysql> コミット; クエリは正常、影響を受けた行は 0 行 (0.00 秒) mysql> 開始します。 クエリは正常、影響を受けた行は 0 行 (0.00 秒) mysql> select * from users where name = 'a' for update; mysql> エンジン innodb ステータスを表示\G ... ------------ 取引 ------------ Trx ID カウンター 4864 トランザクションの n:o < 4862 のパージが完了しました。n:o < 0 の状態を元に戻します: 実行中ですがアイドル状態です 履歴リストの長さ 911 各セッションのトランザクションのリスト: ---トランザクション 4863、アクティブ 37 秒 2 つのロック構造体、ヒープ サイズ 1136、6 行ロック #################ここに注意してください... 次に、ID 2、3、4 のデータを削除し、インデックスされていないフィールドをクエリしてロックし、エンジンのステータスを確認します。 mysql> IDが(2,3,4)であるユーザーから削除します。 クエリは正常、3 行が影響を受けました (0.00 秒) mysql> コミット; クエリは正常、影響を受けた行は 0 行 (0.00 秒) mysql> 開始します。 クエリは正常、影響を受けた行は 0 行 (0.00 秒) mysql> select * from users where name = 'a' for update; mysql> エンジン innodb ステータスを表示\G ... ------------ 取引 ------------ トランザクションIDカウンタ 4870 トランザクションの n:o < 4869 のパージが完了しました。n:o < 0 の状態を元に戻します: 実行中ですがアイドル状態です 履歴リストの長さ 914 各セッションのトランザクションのリスト: ---トランザクション 4869、アクティブ 9 秒 2 つのロック構造体、ヒープ サイズ 1136、3 つの行ロック #################ここに注意してください... ここでテーブル ロックを使用することは、インデックスを使用して特定の行をロックすることはできないため、テーブル全体をロックすることとは異なることがわかります。 2 番目と 3 番目の操作では、ロックされた行も異なります。これは、2 つの操作間のギャップの数が異なるためです。したがって、Next-Key Lock ではなく、テーブル ロックが使用されていることがわかります。最初は (-∞,1],(1,2],(2,3],(3,4],(4,5],(5,∞] がロックされ、2 回目は (-∞,1],(1,5],(5,∞] がロックされました。 方法2: また、次のステートメントを使用してロック情報を表示することもできます。行ロックが使用されていること、間隔 (データを挿入できない) とレコードがロックされているため、Next-Key Lock であることもわかります。 mysql> select ENGINE_TRANSACTION_ID,LOCK_TYPE,LOCK_MODE from performance_schema.data_locks where ENGINE_TRANSACTION_ID in (トランザクション ID) ; +----------------------+-----------+------------+ | ENGINE_TRANSACTION_ID | LOCK_TYPE | LOCK_MODE | +----------------------+-----------+------------+ | 4889 | 表 | IX | | 4889 | レコード | X | | 4889 | レコード | X | | 4889 | レコード | X | +----------------------+-----------+------------+ セット内の行数は 10 です (0.00 秒) LOCK_TYPE: InnoDBの場合、オプションの値はRECORD(行ロック)、TABLE(テーブルロック)です。 LOCK_MODE: InnoDBの場合、可能な値はS[,GAP]、X[,GAP]、IS[,GAP]、IX[,GAP]、AUTO_INC、およびUNKNOWNです。 AUTO_INC と UNKNOWN を除く他のすべてのロック モードには、GAP ロック (存在する場合) が含まれます。 詳細については、MySQL のドキュメント (https://dev.mysql.com/doc/ref...) を参照してください。 テーブルロックテーブル全体を直接ロックし、テーブル内のすべてのレコードに影響します。テーブル読み取りロックとテーブル書き込みロックの互換性については、上記の分析を参照してください。 MySQL には、テーブル読み取りロックとテーブル書き込みロックに加えて、異なる粒度のロックの互換性判断を解決するために存在する、インテンション ロックという特別なテーブル ロックもあります。 意図ロックロックの粒度が異なるため、テーブル ロックの範囲が行ロックの範囲をカバーするため、テーブル ロックと行ロックが競合します。たとえば、トランザクション A がテーブル内のデータ行に行ロックを追加し、次にトランザクション B がテーブル ロックを追加しようとします。通常、競合が発生するはずです。行ロックのみの場合、競合があるかどうかを判断するためにすべてのデータ行を走査する必要があり、これはあまり効率的ではありません。そのため、意図的なテーブル ロックがあります。 インテンション ロックの主な目的は、行ロックとテーブル ロックを共存させることです。行ロックを適用する前に、トランザクションはまずテーブルのインテンション ロックを適用し、成功した後に行ロックを適用する必要があります。注: 意図ロックを申請するアクションはデータベースによって完了されるため、開発者が申請する必要はありません。 インテンション ロックはテーブル レベルのロックですが、トランザクションがテーブル全体ではなくレコードの行を読み取ったり書き込んだりしていることを示します。したがって、インテンション ロック間で競合は発生しません。実際の競合は行ロックを追加するときにチェックされます。 意図ロックは、意図読み取りロック (IS) と意図書き込みロック (IX) に分けられます。 テーブルロックの互換性マトリックス
上記はMySQLロックの関連知識の要約の詳細内容です。MySQLロックの詳細については、123WORDPRESS.COMの他の関連記事に注目してください。 以下もご興味があるかもしれません:
|
>>: three.js を使用してクールなアシッドスタイルの 3D ページ効果を実現します
何が大問題ですか?長時間実行され、長時間コミットされないトランザクションは、大規模トランザクションと...
Keepalive は Vue プロジェクトでのキャッシュによく使用され、基本的な要件を満たすのに非...
データ内に次のような特徴を持つ「 ' 」などの文字が含まれることがあります。 &# ...
参考までに、HTMLフォームの使い方を9つの簡単な例で分析します。具体的な内容は次のとおりです。 1...
序文1. この記事で使用したツールは、https://github.com/gianlucabore...
この記事では、ページ印刷の自動ページングを実現するためのVueの具体的なコードを例として紹介します。...
1. 設置環境Dockerは次のCentOSバージョンをサポートしていますCentOS 6.5 (6...
1. MySQLサービスをシャットダウンする# service mysqld stop 2. rpm...
選択肢がある場合は、UTF-8を使用することをお勧めします。実際、Windows システム自体のプロ...
この記事では、例を使用して MySQL のロック メカニズムと使用方法を説明します。ご参考までに、詳...
この記事では、参考までに、簡単な虫眼鏡効果を実現するためのVueの具体的なコードを紹介します。具体的...
目次1. Docker の 2375 ポートを別のポートに変更します。これは一時的な対策にすぎません...
1. 何ですかreactアプリケーションでは、イベント名はキャメルケース形式で記述されます。たとえ...
Ubuntu 18.04の場合1. sudo apt install python 。コマンドライン...
目次私たちが毎日実行している Linux システムとは何でしょうか? LinuxカーネルとGNUシス...