概要
記事からの翻訳15.7.1 InnoDBのロック次のように、すべての機能がロックの種類が含まれているのmysql-8.0バージョン、の対象となっているロック、次のとおりです。
- 共有ロックと排他ロック
- 意図的ロック
- レコードロック
- ロックギャップ
- キーロックした後、
- 意図的ロックを挿入
- セルフロックを増やします
- 空間インデックスの述語ロック
共有ロックと排他ロック(共有および排他ロック)
InnoDBは、共有および排他ロックロック二つのタイプを含む標準的な行レベルのロックを実装します
- ロックがトランザクションのレコードを持つことができる共有ロック(Sロック)行読み出されます
- 排他ロック(Xロック)は、ロックを所有しているトランザクションが行のレコードを更新または削除することができます
トランザクションは、T1回線rにロックを共有している場合は、ラインR、以下のアプローチの異なるトランザクションT2リクエスト用:
- T2は、ロックを共有している、すぐに共有ロック、最終T1およびT2を付与することができます
- T2はすぐに排他ロックを付与することはできません
トランザクションT1は、行Rに排他ロックを持っている場合、別のトランザクションT2のために、行R上の任意のロックを付与しないことができ、その後、T2は、行Rに対するそのロックを解除するためにT1を待たなければなりません
意図的ロック(意図ロック)
InnoDBは、行およびテーブルロックは、例えば、存在できるように、複数粒度ロックをサポートLOCK TABLE ... WRITE
文が指定されたテーブルに排他ロックを使用することができます。マルチ粒度ロックを達成するために、InnoDBは意図的ロックを使用します
意図ロックが使用したい表の後のロック列のタイプをトランザクションを表し、テーブルレベルのロック、あり、意図的ロックの2種類があります。
- 意図共有ロック(ロックである)、いくつかの共有ロックのトランザクションを表現する傾向があるが、テーブルの行に設けられています
- 意図排他ロック(IXロック)は、テーブル内の行の一部の取引を示す傾向にある排他ロックを設定します
たとえば、SELECT ... FOR SHARE
あなたがISロックを設定し、SELECT ... FOR UPDATE
ロックIXを設定し、
次のように意図的ロックは、合意されました:
- 取引の前に行をロック共有テーブルを得ることができる、あなたは最初に取得する必要がありますテーブルの上にロックされるか、テーブルの上に強力なロック
- トランザクションが表に排他ロックにいくつかの行を取得するには、まずテーブルの上にIXロックを取得する必要があります
以下の行列によって要約テーブルレベルロックの互換性:
要求トランザクションがロックの現在の存在と互換性がある場合、ロックが付与されます。競合が付与されていない場合は、ロックが競合が解放されるまで、トランザクションが待機します。それがデッドロックデータベースにつながるとして、紛争の状況でロックされて付与されたことはありません意図的ロックは、(のようなフルテーブルリクエスト以外のものをブロックしないLOCK TABLES ... WRITE
)、主な目的は、意図的ロックまたは誰かがテーブル内の行をロックしようとしている示すことです
意図は、トランザクションデータをロックSHOW ENGINE INNODB STATUS
コンテンツと、この形でのInnoDBモニタ出力は、実質的に以下の通りです。
TABLE LOCK table `test`.`t` trx id 10080 lock mode IX
复制代码
レコードのロック(レコードロック)
レコードロックは、ロックインデックスレコードです。例えば、SELECT c1 FROM t WHERE c1 = 10 FOR UPDATE;
他のトランザクションは、更新を挿入防止、及びテーブルC1 = 10トンの行を削除します
テーブルがインデックスに定義されていない場合でも、レコードロックは常にインデックスレコードをロックします。この場合、InnoDBは隠されたクラスタ化インデックスを作成し、ロック記録するには、このインデックスを使用します
トランザクション内のデータを記録するロックSHOW ENGINE INNODB STATUS
この形態の内容とInnoDBのモニタ出力は、実質的に以下の通りです。
RECORD LOCKS space id 58 page no 3 n bits 72 index `PRIMARY` of table `test`.`t`
trx id 10078 lock_mode X locks rec but not gap
Record lock, heap no 2 PHYSICAL RECORD: n_fields 3; compact format; info bits 0
0: len 4; hex 8000000a; asc ;;
1: len 6; hex 00000000274f; asc 'O;;
2: len 7; hex b60000019d0110; asc ;;
复制代码
ロックギャップ(GAPロック)
ギャップロックは、ロックのような最初のインデックス及び最後のインデックスのギャップの前または後に、インデックスレコードとの間のギャップであるSELECT c1 FROM t WHERE c1 BETWEEN 10 and 20 FOR UPDATE;
にかかわらず、列は、任意のそのようなものがあるかどうか、別の取引額15をt.c1に挿入されなくなります値は、範囲内の任意の値の存在がロックされるので
このギャップは、空であっても単一のインデックス、複数のインデックスを、及ぶことができます
ギャップロックは、パフォーマンスと並行性とのトレードオフのいくつかである、唯一の特定のトランザクション分離レベルに作用します
(ない含む基準は複数列一意のインデックスの場合の列の一部のみ、この場合には、ギャップがまだロックを使用するを含む)空間ロックを使用しない文の一意な行を検索するための一意のインデックスを使用して、例えば、idカラム場合一意のインデックスを使用して、次のステートメントは、前列のギャップの他のセッションが挿入されているか否かに関わらず、インデックスレコードロックを使用してのみロック100のIDのために使用されます。
SELECT * FROM child WHERE id = 100;
复制代码
非一意インデックスID列がインデックス付け、または使用されない場合、文は、ギャップフォーマロックであります
特に、相互にロック競合は、異なるトランザクションによってギャップに保持することができ、例えば、トランザクション保持共有スペースロック(隙間Sロック)ギャップに、トランザクションBは、(ギャップが同じクリアランスに排他ロックを維持することができますXロックギャップ)。ロックギャップ矛盾する理由を許可すると、インデックスから履歴のクリアならば、あなたは別のトランザクションによって、レコードのリテンションギャップロックをマージしなければならないということです
InnoDBのギャップロックは唯一の目的は、ギャップがギャップに挿入し、他のトランザクションをロック防止するためであることを意味する「純粋阻害」、です。ロックは、相互に矛盾しない、彼らは同じ機能を持っている、スペースと行ロックギャップを共有することは、彼との間に違いロックされていない、ギャップ、ギャップロックトランザクションが同じ空間で別のトランザクションに行わクリアランスロックロックを防ぐことはできません共存させることができます
あなたは、このようなトランザクション分離レベルが設定されているように明確な文によるロックギャップを無効にすることができますREAD COMMITTED
。この場合、検索とインデックスのギャップが無効にロックスキャンするために、チェックのみに作用し、外部キー制約は、キーを繰り返し
使用するREAD COMMITTED
分離レベルは、他の効果を持つことになります、MySQLが評価するWHERE
条件を、レコードは行ロックと一致していないリリースします。以下のためにUPDATE
それはMySQLへ提出することができるように声明、「半同一」のInnoDBの実装は、最新バージョンを読み取るために、MySQLが判断できるかどうかと、行の条件に一致UPDATE
WHERE
キーイングした後(ネクストキーロック)
キーイングした後、それがインデックスに記録された记录锁
インデックスレコードと前の间隙锁
組み合わせ
InnoDBは、行レベルにロックするよう使用:検索またはスキャンテーブルインデックス、それはインデックスが発生したレコードまたは排他的ロックを共有ロックを設定し、従って、行レベルロックは、インデックスレコードロックは実際に
インデックスレコード上のキーロックした後も、キーロックは、インデックスレコードロックプラスインデックスレコードの前にギャップのギャップロックされた後と言うことです「ギャップ」を、記録する前に、インデックスに影響を与えます。ロックのインデックスRにおけるセッション・レコードの共有または排他ロックがある場合、他のセッションが順番にインデックスR前のギャップで新しいインデックスレコードを挿入することはできません
10,11,13を含むインデックス値を仮定し、そして20、インデックスは括弧間隔エンドポイントが除外示す前記キーロックキー、後に覆われていてもよい、角括弧内に含まれるエンドポイント(すなわち、開閉現在のセットを示しますコンセプト):
(negative infinity, 10]
(10, 11]
(11, 13]
(13, 20]
(20, positive infinity)
复制代码
最後の間隔のため、指標の実際の値の任意のレコードよりも屈折率の最大値でギャップ、および値「supermum」擬似をロックするロックキー後、supermunインデックスレコードが真でない、したがって、実際には、キーの後ギャップをロックした後にのみ、最大インデックス値をロックする(キーロックは、最後のギャップの後を意味します)
デフォルトでは、InnoDBはでREPEATABLE READ
分離レベル下での動作、この場合には、InnoDBはそれによってファントムリードを防止する、検索キーロックとインデックススキャンを使用して
キーロック中のトランザクションデータSHOW ENGINE INNODB STATUS
内容とInnoDBは、この出力は、実質的に以下の形式で監視します。
RECORD LOCKS space id 58 page no 3 n bits 72 index `PRIMARY` of table `test`.`t`
trx id 10080 lock_mode X
Record lock, heap no 1 PHYSICAL RECORD: n_fields 1; compact format; info bits 0
0: len 8; hex 73757072656d756d; asc supremum;;
Record lock, heap no 2 PHYSICAL RECORD: n_fields 3; compact format; info bits 0
0: len 4; hex 8000000a; asc ;;
1: len 6; hex 00000000274f; asc 'O;;
2: len 7; hex b60000019d0110; asc ;;
复制代码
意図的ロックを挿入(挿入インテンションロック)
意図ロック・インサート、ラインがによって挿入される前INSERT
、間質ロック設定操作。このように挿入されるロックの意思を示す:同じインデックスギャップは、ギャップ内の同じ位置に挿入されていない場合、複数のトランザクションに挿入、互いに待つ必要がありません
図4は、二つの別々のトランザクションが4-7をロックするために意図的ロックの間に挿入間隙を用いて、それぞれ、排他的ロック・インサート行を取得する前に、5と6の値を記録する試みが挿入された記録と7の指標があると想定されます動作が競合しないので、彼らは、お互いをブロックしません。
次の例では、ロックするロックを使用しての意図を挿入し、排他ロックを取得する前にレコードを挿入を示しています。この例では、それぞれ2つのクライアント、AおよびBを含みます
クライアントAは、テーブルインデックスレコードが2つ(99及び102)を含んで作成し、トランザクションを開始し、トランザクションIDは、ロックは、記録前に放電ギャップロック102を含む、排他的ロックに配置されるインデックスレコード100よりも大きいです。
mysql> CREATE TABLE child (id int(11) NOT NULL, PRIMARY KEY(id)) ENGINE=InnoDB;
mysql> INSERT INTO child (id) values (90),(102);
mysql> START TRANSACTION;
mysql> SELECT * FROM child WHERE id > 100 FOR UPDATE;
+-----+
| id |
+-----+
| 102 |
+-----+
复制代码
クライアントBは、排他ロックを取得するために待っている間に挿入意図はトランザクションをロック用いて、隙間に挿入されたレコードのトランザクションです。
mysql> START TRANSACTION;
mysql> INSERT INTO child (id) VALUES (101);
复制代码
意図的ロックトランザクションデータの挿入SHOW ENGINE INNODB STATUS
コンテンツをし、InnoDBは、この出力は、実質的に次のような形式で監視します。
RECORD LOCKS space id 31 page no 3 n bits 72 index `PRIMARY` of table `test`.`child`
trx id 8731 lock_mode X locks gap before rec insert intention waiting
Record lock, heap no 3 PHYSICAL RECORD: n_fields 3; compact format; info bits 0
0: len 4; hex 80000066; asc f;;
1: len 6; hex 000000002215; asc " ;;
2: len 7; hex 9000000172011c; asc r ;;...
复制代码
ロックインクリメント(AUTO-INCロック)
増分ロックは、で挿入されるAUTO_INCREMENT
テーブルロックロックトランザクションの特別な列が自己増力特性を使用します。トランザクションの値をテーブルに挿入された場合、最も簡単な場合には、その後、他のトランザクションは、プライマリ・キー値の連続的な行に挿入するために、最初のトランザクションを受信し、独自のテーブルを実行挿入を待たなければなりません
innodb_autoinc_lock_mode
予測可能なあなたのため、成長シーケンスと同時挿入操作の最大量との間のトレードオフを可能にするアルゴリズムをロックするための増分を制御する設定オプション
空間インデックスの述語ロック(空間索引の述語ロック)
InnoDBは含む空間カラムサポートSPATIAL
インデックス(参照11.5.9空間分析を最適化します)
関与対処するためにSPATIAL索引
ロックの操作を、キーロックはよくサポートされていないREPEATABLE READ
と、SERIALIZABLE
トランザクション分離レベルは、そこには絶対的な注文キューブのコンセプトではありませんので、正確に「キー」であるかを判断することはできません
含むサポートするSPATIAL索引
分離レベルテーブルを、InnoDBは使用谓词锁
、SPATIAL索引
最小外接矩形(MBR)値を含む、InnoDBは、クエリが一貫インデックス読み取りを強制するためのMBR値述語内に配置されたロック、他のトランザクションを挿入することができない、または変更し、クエリ照合行
ます。https://juejin.im/post/5cef617e518825095b331cafで再現