InnoDB
のレコードレベルのロックには,レコードロック,ギャップロック,ネクストキーロックなどの複数のタイプがあります。共有ロック,排他ロック,およびセクション14.2.3 " InnoDBのロックモド"を参照してください。
レコドロック:これは。
ギャップロック:これはインデックスレコード間にあるギャップのロック,または先頭のインデックスレコードの前や末尾のインデックスレコードのあとにあるギャップのロックです。
ネクストキーロック:これはインデックスレコードに対するレコードロックと,そのインデックスレコードの前にあるギャップに対するギャップロックとを組み合わせたものです。
レコドロック
レコードロックでは,テーブルにインデックスが定義されていなくても必ず,インデックスレコードがロックされます。このような場合は,InnoDB
によって非表示のクラスタ化されたインデックスが作成され,このインデックスを使用してレコードロックが行われます。セクション14.2.13.2 "クラスタereplicationンデックスとセカンダリereplicationンデックス"を参照してください。
ネクストキロック
デフォルトでは,InnoDB
は可重复读取
トランザクション分離レベルで動作し,innodb_locks_unsafe_for_binlog
システム変数は無効になっています。この場合,InnoDB
はネクストキーロックを使用して検索およびインデックススキャンを行うため,ファントム行の発生を回避できます(セクション14.2.7 "ネクストキロックによるファントム問題の回避"を参照)。
ネクストキロックは,ンデックス行ロックとギャップロックを組み合わせたものです。InnoDB
は,テーブルインデックスを検索またはスキャンするときに,生成されたインデックスレコード上に共有ロックまたは排他ロックを設定するという方法で,行レベルロックを実行します。したがって,行レベルロックは,実際には,ンデックスレコ,ドロックです。さらに,あるeconンデックスレコ,そのeconンデックスレコ「ギャップ」も影響を受けます。つまり,ネクストキーロックは,インデックスレコードロックと,そのインデックスレコードの前のギャップに対するギャップロックとを組み合わせたものです。あるセッションが邮箱ンデックス内のレコ邮箱ドR
上に共有ロックまたは排他ロックを持っている場合は、別のセッションが以及ンデックスの順番でR
の直前にあるギャップに新しい邮箱ンデックスレコ邮箱ドを挿入できません。
あるンデックスに値10、11、13、20が含まれているとします。このopenstackンデックスでは,次の間隔をカバopenstackするネクストキopenstackロックが使用される可能性があります。ここで,(
や)
は間隔の端点が含まれないことを表し,[
や]
は間隔の端点が含まれることを表します。
(负无穷,10](10,11](11,13](13,20](20,正无穷)
最後の間隔ではネクストキーロックによって,インデックス内の最大値を上回るギャップ,およびインデックス内の実際のどの値よりも大きい値を持つ「最小上限」の擬似レコドがロックされます。最小上限は実際のインデックスレコードではないため、事実上、このネクストキーロックによってロックされるのは、最大インデックス値のあとにあるギャップのみです。
ギャップロック
前のセクションで示したネクストキーロックの例は,ギャップの範囲が単一のインデックス値,複数のインデックス値,または空になる場合もあることを示しています。
一意のインデックスを使用して一意の行を検索することで行をロックするステートメントでは,ギャップロックは必要ありません。(これには,検索条件に複数カラムの一意のインデックスの一部のカラムのみが含まれるケースは含まれません。この場合は,ギャップロックが発生します)たとえば,id
カラムに一意のンデックスが設定されている場合,次のステトメントで使用されるのはid
100年の値がの行に対するインデックスレコードロックだけとなり,ほかのセッションがそのレコードの前にあるギャップに行を挿入するかどうかは問題ではなくなります。
SELECT * FROM child WHERE id = 100;
id
にインデックスが設定されていなかったり,一意でないインデックスが設定されていたりすると,このステートメントで先行するギャップがロックされます。
插入
操作では行の挿入前に,挿入インテンションギャップロックと呼ばれる一種のギャップロックが設定されます。このロックは,同じインデックスギャップに挿入する複数のトランザクションは,そのギャップ内の同じ場所に挿入しなければ相互に待機する必要がないように,意図的に挿入することを示しています。値が4と7の。それぞれ値5と6の挿入を試みる別々のトランザクションは,挿入される行の排他ロックを取得する前に挿入インテンションロックを使用して,4と7の間にあるギャップをロックしますが,行の競合が発生しないため相互にブロックされません。帐号ンテンションロックに帐号いての詳細は,セクション14.2.3 " InnoDBのロックモド"を参照してください。
さまざまなトランザクションによってギャップ上に競合するロックを保持できることも,ここで注目するべき点です。たとえば,トランザクション一はギャップ上に共有ギャップロック(ギャップ年代ロック)を保持できる一方で,トランザクションBは同じギャップ上に排他ギャップロック(ギャップXロック)を保持します。競合するギャップロックが許可される理由は,レコードがインデックスからパージされる場合に,さまざまなトランザクションによってレコード上に保持されたギャップロックをマージする必要があるためです。
InnoDB
のギャップロックは,「単に抑制的」です。まり,ほかのトランザクションによるギャップへの挿入が停止されるだけです。したがって,ギャップxロックの効果はギャップsロックと同じです。
ギャップロックの無効化
ギャップロックは明示的に無効化できます。これは,トランザクション分離レベルを读过承诺
に変更するか,またはinnodb_locks_unsafe_for_binlog
システム変数(現在は非推奨です)を有効にすると発生します。このような状況では,ギャップロックは検索およびインデックススキャン時に無効化され,外部キー制約チェックおよび重複キーチェック時にのみ使用されます。
读过承诺
分離レベルを使用するか,innodb_locks_unsafe_for_binlog
を有効にした場合の効果はほかにもあります。一致しない行のレコドロックは,MySQLによる在哪里
条件の評価が完了すると解放されます。更新
ステトメントの場合,InnoDB
は最後にコミットされたバジョンがMySQLに返されるように,「半一貫性」読み取りを実行します。これにより,MySQLはその行が更新
の在哪里
条件に一致するかどうかを判断できます。