一般に,ロック読み取り、更新
,または删除
では、SQLステートメントの処理時にスキャンされるすべてのインデックスレコード上に,レコードロックが設定されます。行を除外する在哪里
条件がステトメント内に存在するかどうかは,関係ありません。InnoDB
には正確な在哪里
条件が記憶されませんが、スキャンされた以及ンデックスの範囲は認識されます。通常,ロックはレコドの直前にある「ギャップ」への挿入もブロックするネクストキロックです。ただし,ギャップロックは明示的に無効にすることができます。これにより,ネクストキロックが使用されなくなります。詳細は,セクション14.2.6 " InnoDBのレコド,ギャップ,およびネクストキロック"を参照してください。トランザクション分離レベルによって,どのロックが設定されるのかも影響を受けます。セクション13.3.6 " set transaction構文"を参照してください。
検索でセカンダリopenstackンデックスが使用され,設定されるopenstackンデックスレコopenstackドのロックが排他的である場合,InnoDB
は対応するクラスタ化されたンデックスレコドを取得し,それらにロックを設定することも行います。
共有ロックと排他ロックの違いにいては,セクション14.2.3 " InnoDBのロックモド"を参照してください。
ステートメントに適したインデックスがなく,MySQLがステートメントを処理するためにテーブル全体をスキャンする必要がある場合は,テーブルのすべての行がロックされます。その結果,そのテブルへのほかのユザによるすべての挿入がブロックされます。クエリで不必要に複数の行がスキャンされないように,適切なンデックスを作成することが重要です。
选择……更新
または选择……共享模式锁定
では,スキャンされた行にいてはロックが取得され,在哪里
句に指定された条件を満たさないなどの理由で結果セットに含める対象から除外された行については,ロックが解放されることが予想されます。ただし場合によっては,クエリーの実行中に結果行とその元のソースとの関係が失われたために,行のロックがすぐに解除されない可能性もあります。たとえば联盟
では,スキャン(およびロック)されたテーブル内の行が,結果セットに含める対象となるかどうかの評価前に,一時テーブルに挿入される可能性があります。この状況では,一時テーブル内の行と元のテーブル内の行との関係は失われているため,クエリー実行が終了するまで後者の行のロックは解除されません。
InnoDB
は、次のように特定のロックタ以及プを設定します。
选择……从
は一貫性読み取りであり,デタベ,スのスナップショットを読み取り,トランザクションの分離レベルが可序列化的
に設定されなければロックを設定しません。可序列化的
レベルの場合,検索で見。选择……从…共享模式锁定
では,検索で見。选择……从…更新
は,検索で見选择……从…共享模式锁定
を実行したり,特定のトランザクション分離レベルで読み取ったりすることをブロックします。一貫性読み取りでは,読み取られたビュ内に存在するレコドに設定されたロックはすべて無視されます。更新……在那里……
は,検索で見。删除…在那里……
は,検索で見。插入
は,挿入される行に排他ロックを設定します。このロックは,ネクストキーロックではなくインデックスレコードロックである(つまり,ギャップロックが存在しない)ため,ほかのセッションが挿入された行の前にあるギャップに挿入することは回避されません。行の挿入前に、挿入以及ンテンションギャップロックと呼ばれる一種のギャップロックが設定されます。このロックは,同じインデックスギャップに挿入する複数のトランザクションは,そのギャップ内の同じ場所に挿入しなければ相互に待機する必要がないように,意図的に挿入することを示しています。値が4と7の。それぞれ値5と6の挿入を試みる別々のトランザクションは,挿入される行の排他ロックを取得する前に挿入インテンションロックを使用して,4と7の間にあるギャップをロックしますが,行の競合が発生しないため相互にブロックされません。
重複キエラが発生すると,重複。複数のセッションが同じ行を挿入しようとしているときに,別のセッションがすでに排他ロックを取得していた場合は,このように共有ロックを使用することでデッドロックが発生する可能性があります。これは,別のセッションがその行を削除した場合に発生する可能性があります。
InnoDB
テブルt1
の構造が次のようになっているとします。CREATE TABLE t1 (i INT, PRIMARY KEY (i)) = InnoDB;
次に,3のセッションが次の処理を順番に実行するものとします。
セッション1:
开始事务;INSERT INTO t1 VALUES(1);
セッション2:
开始事务;INSERT INTO t1 VALUES(1);
セッション3:
开始事务;INSERT INTO t1 VALUES(1);
セッション1:
回滚;
セッション1による最初の処理では,行の排他ロックが取得されます。セッション2と3の処理ではどちらも重複キーエラーが発生し,どちらのセッションも行の共有ロックをリクエストします。セッション1はロールバック時に行の排他ロックを解放し,キュー内のセッション2と3の共有ロックリクエストが付与されます。この時点でセッション2と3でデッドロックが発生します。どらも他方が保持している共有ロックのために,行の排他ロックを取得できません。
キー値が1の行がテーブルに含まれている場合も似たような状況が発生し,3つのセッションが次の処理を順番に実行します。
セッション1:
开始事务;DELETE FROM t1 WHERE i = 1;
セッション2:
开始事务;INSERT INTO t1 VALUES(1);
セッション3:
开始事务;INSERT INTO t1 VALUES(1);
セッション1:
提交;
セッション1による最初の処理では,行の排他ロックが取得されます。セッション2と3の処理ではどちらも重複キーエラーが発生し,どちらのセッションも行の共有ロックをリクエストします。セッション1はコミット時に行の排他ロックを解放し,キュー内のセッション2と3の共有ロックリクエストが付与されます。この時点でセッション2と3でデッドロックが発生します。どらも他方が保持している共有ロックのために,行の排他ロックを取得できません。
插入……重复密钥更新
は,重複キーエラーが発生したときに,更新される行に共有ロックではなく,排他ネクストキーロックが配置されるという点で,単純な插入
と異なります。取代
は,一意のキ,が競合していなければ,插入
と同様に動作します。それ以外の場合は,置換される行に排他ネクストキーロックが配置されます。Insert into t select…从哪里…
は,T
に挿入された各行に、ギャップロックなしの排他。トランザクション分離レベルが读过承诺
である場合,またはinnodb_locks_unsafe_for_binlog
が有効になっていて,トランザクション分離レベルが可序列化的
でない場合,InnoDB
は一貫性読み取り(ロックなし)として年代
上で検索を実行します。それ以外の場合,InnoDB
は年代
から取得した行に共有ネクストキロックを設定します。InnoDB
は,後者の場合にロックを設定する必要があります。バックアップからのロールフォワードリカバリ時には,すべてのSQLステートメントを元とまったく同じ方法で実行する必要があります。创建表…选择……
は,插入……选择
の場合と同様に,选择
を共有ネクストキロックを使用して実行するか,一貫性読み取りとして実行します。構造文
替换成t SELECT…从……
または更新…WHERE col IN (SELECT…)从s…)
で选择
が使用されると,InnoDB
はテブル年代
の行に共有ネクストキロックを設定します。InnoDB
は,テブル上に事前に指定されたAUTO_INCREMENT
カラムの初期化中に,AUTO_INCREMENT
カラムに関連付けられた邮箱ンデックスの最後に排他ロックを設定します。InnoDB
では,自動インクリメントカウンタにアクセスするときに,ロックがトランザクション全体の最後までではなく,現在のSQLステートメントの最後まで続く,特別なAUTO-INC
テブルロックモドが使用されます。AUTO-INC
テブルロックが保持されている間は,ほかのセッションはそのテブルに挿入できません。セクション14.2.2 " InnoDBのトランザクションモデルおよびロック"を参照してください。InnoDB
は,ロックを設定せずに,事前に初期化されたAUTO_INCREMENT
カラムの値をフェッチします。外键
制約がテーブル上で定義されている場合は,制約条件をチェックする必要がある挿入,更新,または削除が行われると,制約をチェックするために,参照されるレコード上に共有レコードレベルロックが設定されます。InnoDB
は,制約が失敗する場合に備えて,これらのロックの設定も行います。锁表
はテブルロックを設定しますが,これらのロックを設定するInnoDB
レeconeconヤMySQLレeconeconヤ。InnoDB
は,Innodb_table_locks = 1
(デフォルト)か演算器自动提交= 0
の場合にテブルロックを認識し,InnoDB
よりも上位のMySQLレ。それ以外の場合は,
InnoDB
の自動デッドロック検出では,このようなテブルロックが関与するデッドロックを検出できません。また,この場合には上位のMySQLレイヤーは行レベルロックを識別しないため,現在別のセッションが行レベルロックを保持しているテーブル上でテーブルロックを取得できます。ただし,セクション14.2.10 "デッドロックの検出とロルバック"で説明したように,これによりトランザクションの完全性が危険にさらされることはありません。セクション14.6.7 " InnoDBテブル上の制限"も参照してください。