(MySQLの)選択ロックの歴史の中で最も包括的な分析を[ターン]

入門

私たちは、インタビュアーはあなたがインタビューの中で、次の6つのSQLを区別尋ねる満たしていないこと

select * from table where id = ? select * from table where id < ? select * from table where id = ? lock in share mode select * from table where id < ? lock in share mode select * from table where id = ? for update select * from table where id < ? for update

あなたははっきり言うことができる場合は、そのロックされたかどうかを六つの異なるトランザクション分離レベルでは、このSQL、プラス共有ロックまたは排他ロック、記事がアップ見ていないことを意味し、ギャップがある場合にロック。
あまりにもこの分野でのこれまでのオンライン記事、片側ので、この記事を書くための理由は、半分だけ言って、それらのほとんどは、分離レベルを指定し、しませんでしたwhereインデックスの条件は、列が続くかどうか。ここでは、それらのほとんどはおよそ明確ではない、私はエラーでこれらの記事を一覧表示しません、と私たちは百度を所有することができます。
OK、私は3つの質問を自問、この質問に答えるしたいです

  • 現在のトランザクション分離レベルとは何ですか
  • ID列は、インデックスを存在します
  • クラスタ化インデックスまたは非クラスタ化インデックスのインデックスが、それはありますか?

OK、答えを開始

テキスト

この記事では、読者を想定して、私の読み「の原則のMySQL(InnoDBの)インデックス」あなたは、金額を見ていない場合は、右の三つの言葉を覚えています

  • InnoDBのクラスタ化インデックスは、クラスタ化インデックスの主キーにデフォルトとして、存在している必要があります
  • いくつかの指標がありますが、木は(状況にハッシュインデックスを考慮せずに)B +木であります
  • リーフ・ノードは、ディスク上の実際のデータのインデックスをクラスタ化されました。リーフノードまたはB +ツリーインデックスをクラスタ化するポインティング非クラスタ化インデックスのインデックス。

基礎下のロングったらしいポイント

ロックタイプ

共有ロック(Sロック):と仮定トランザクションT1とデータの共有ロックは、トランザクションT2ができるデータAを読んで、あなたがすることはできませんデータAを変更します
排他ロック(Xロック):トランザクションT2が思うトランザクションT1とデータの共有ロック、することはできませんデータAを読んで、あなたがすることはできませんデータAを変更します
我々updatedeleteそして一緒に行レベルロックと他のステートメントがロックされています。だけLOCK TABLE … READLOCK TABLE … WRITEあなたは、テーブルレベルのロックを申請することができます。
意図共有ロック(ロックです):トランザクションの前に取得(任意の行/または全表)Sロック、我々が最初に追加されますテーブルの上にロックISが配置されています。
意図排他ロック(IXロック):トランザクションの前に取得する(任意の行/またはフル・テーブル)Xロックは、テーブル上のIXロックが配置されている第一の増加となります。

意図の有無は、目的をロック?

OK、ここに意図的ロックの存在の目的について話をします。テーブルの上にいくつかのレコードをロックすると仮定取引Tlの、Xロックは、その後、時間表のIXロックは、すなわち、意図排他ロックが存在します。その後、時刻T2は、トランザクション実施するLOCK TABLE … WRITE直接ロックの存在は、ロック競合を持っているかどうかを判定することができる意図に応じて、テーブルレベルロック要求を。

ロックアルゴリズム

私の見解では、公式ドキュメントからです:
https://dev.mysql.com/doc/refman/5.7/en/innodb-locking.html
人工派生し、独自の洞察を追加します。
[OK]を、次の三つを覚えて、これは使用するのに十分である
Record Locks:単に行に翻訳され、それをロックします。注意、ロックは、インデックスレコードをロックされています!ロックは、インデックス付きにしていないラインです。注意、InnoDBは、クラスタ化インデックスが存在しなければならないので、行ロックは、最終的には、クラスタ化インデックスに分類されます!
Gap Locks:ロックは、データを挿入する他の事を防ぐために、一つだけの目的であるギャップ指数、翻訳ギャップロックシンプルです。Read Committed分離レベル、ギャップはロックを使用しません。ここで私は、公式ウェブサイトにより分離レベルを追加すべきであるRead Committedため、このような分離レベルとしてロックギャップを、使用しない、低い時のRead Uncommited時間、何のギャップロックがありませんでした。ときに分離レベルRepeatable ReadSerializableがある場合にギャップがロックされます。
Next-Key Locks:これは、以下のように理解されているRecord Lockインデックスの前に+ Gap Lock覚えておいて、インデックスギャップの前にロックされています!インデックスには、そのような値、10,11,13および20が含まれています。次いで、ギャップのロック範囲は、以下のように

(negative infinity, 10]
(10, 11]
(11, 13] (13, 20] (20, positive infinity)

現在の読書と読書のスナップショット

最後に基本的には、私たちは後ろの分析の基礎である、読書を主張します!
MySQLでの現在の読み取りにスナップショットを選択して、読んで、次の文を実行

select * from table where id = ?;

スナップショットの読み取りを行い、読み取りがロックされていないデータベースレコードのスナップショットのバージョンです。(この文は、分離レベルにあるがSerializable設定されていない、私は後で追加されます。)
そして、実行

select * from table where id = ? lock in share mode;

行われ、レコードは(共有ロック)をロックするSプラス読みます

select * from table where id = ? for update

プラスXはその後、レコードロック(排他ロック)を読み込みます

プラステーブルロックまたは行は、それをロック?

この時点では、それらが示され弱いから強いに次のようにのは、4つのトランザクション分離レベルを思い出してみましょう:

  • Read Uncommited(RU):非コミット読み取り、トランザクションが別のコミットされていないトランザクションからデータを読み取ることができます!
  • Read Committed (RC):コミット読み取り、トランザクションが別のトランザクションが提出されたデータを読み取ることができます!
  • Repeatable Read (RR):幻の生成を回避するための反復可能読み取り、ギャップに参加するロックは、ある程度まで読んでください!ある程度までしか、完全には避けられない!私はまた、ギャップのレベルからロックへの参加を始めたことを覚えておいてください!次の記事で説明します、注意(ダウンこの文は、バックアップに便利です)!
  • Serializable:シリアル化は、読んで、そのレベルでの書き込み、およびすべてのシリアル化されたselect文が自動的に追加されlock in share mode、共有ロックを使用すること。したがって、この分離レベルでは、現在の読み出しではなく、スナップショットの読み出しを使用しています。

どのようなテーブルロックまたはロー・ロックについて、あなたは最も人気のあるオンラインの説明を見ることができることはつまり、

InnoDBの行ロックを達成するために、データ・ブロック内の対応するデータ線によってロックされているMySQLとオラクル、異なるロック、上のインデックス項目にインデックスすることによって達成されます。この特性手段を達成するためのInnoDB行ロック:インデックスのみの条件を介してデータを取得するために、唯一のInnoDBの行レベルのロック、そうでない場合は、InnoDBのテーブルロックを使用します!

私たちは、これらの単語について検索することができ、あなたは私をコピーすべてが、私はあなたをコピーします。さて、この文自体は、二つのミスを持っています!
エラー:テーブルをロックしますが、使用するロックテーブルの操作によって達成されないNext-Key Locks!ロックのギャップ+ロック操作が達成されるとのラインがテーブルをロックして、理解することができる
と仮定すると、たとえばI、説明の便宜のためにテーブルデータ、PIDプライマリキーインデックスとして

PID(INT) 名前(varchar型) NUM(INT)
1 AAA 100
2 BBB 200
7 CCC 200

声明(インデックスなしの名前の欄)を実行

select * from table where name = `aaa` for update

このとき、これら3つのレコードがpid = 1,2,7に存在するロックライン(ロックされた行)。さらに、ギャップロックが(-∞、1)(1,2)(2,7)(7、+∞)に(ギャップがロック)があります。このように、テーブル全体のロック錯覚を与えます!

ps:疑いの結論は、自分自身の実行可能show engine innodb status;文の分析を。

エラー2:すべての記事は、分離レベルを言及していません!
私は、上記述べた、テーブルをロックすることができたことに注意し、行ロックロック+ギャップによって達成されます。まあ、RURCのギャップは、このビューでは、そこにあるロックしないRUと、RCまたそれに設定?
そのため、この引数は唯一RRかつSerializable有効です。分離レベルの場合RURC、関係なく、インデックスに記載されている条件があるかどうか、テーブルをロックしないであろうが、ちょうどラインをロック!

分析

のは、以下の表、PIDプライマリキーインデックスがあると仮定すると、質問に答えるために始めましょう

PID(INT) 名前(varchar型) NUM(INT)
1 AAA 100
2 BBB 200
3 BBB 300
7 CCC 200

非インデックス列のRC / RU +条件

(1)select * from table where num = 200
任意ロックすることなく、それがスナップショットの読み取りです。
(2)select * from table where num > 200
任意ロックすることなく、それがスナップショットの読み取りです。
(3)select * from table where num = 200 lock in share mode
NUM = 200は、二つのレコードが存在する場合。PID = 2,7に対応するこれら二つのレコードは、このように現在の読み出しを使用して、クラスタ化インデックスPID = 2,7に行レベルのロックを適用S。
(4)select * from table where num > 200 lock in share mode
NUM> 200は、レコードが存在する場合。このレコードは、現在のリードを使用して、線S-レベルロックでPID = 3、そう= 3のPIDにクラスタ化インデックスに対応します。
(5)select * from table where num = 200 for update
NUM = 200は、二つのレコードが存在する場合。PID = 2,7に対応するこれら二つのレコードので、現在のリードを使用して、PID = 2,7に行レベルロックのXクラスタ化インデックスを追加します。
(6)select * from table where num > 200 for update
NUM> 200は、レコードが存在する場合。このレコードは、PID = 3ので、現在のリードを使用して線とXレベルロックでPID = 3クラスタ化インデックスに対応します。

RC / RU +条件は、インデックスをクラスタ化されています

まあ、PIDを知っている必要があります誰もがそうPID使用は、クラスタ化インデックスで、主キー列です。実際にはこのような状況と非インデックス付きの列のRC / RU +条件状況が似ています。
(1)select * from table where pId = 2
任意ロックすることなく、それがスナップショットの読み取りです。
(2)select * from table where pId > 2
任意ロックすることなく、それがスナップショットの読み取りです。
(3)select * from table where pId = 2 lock in share mode
読み出し電流のためのクラスタ化されたPID = 2のインデックス、プラスSロックです。
(4)select * from table where pId > 2 lock in share mode
PID = 3,7、プラスSロックにクラスタ化インデックスに、読み出し電流。
(5)select * from table where pId = 2 for update
PID = 2、プラスXロックにクラスタ化インデックスに電流を読み出します。
(6)select * from table where pId > 2 for update
PID = 3,7、プラスXロックにクラスタ化インデックスに電流を読み出します。

ここでは、あなたが質問を持っていること

条件がインデックス化されているのはなぜ追加しないで、ロックされた状況は同じですか?

[OK]を、実際には、それは同じではありません。RC / RUの分離レベルでは、MySQLサーバが最適化されています。フル・テーブルがクラスタ化インデックス、全表ロックによって走査されるが条件は、列インデックスでない場合。しかし、MySQLサーバは、レイヤをフィルタリングし、あなたが結果は同じに見える終わるように、リリースの条件はすぐに、ロックアウト満たしていません。しかし、非インデックス列のRC / RU +条件この場合よりもロック解除プロセスよりも多くの条件を満たしていません!

RC / RU +条件は、非クラスタ化インデックスです

私たちは、num個の列上の非ユニークなインデックス上に構築します。この時点で、クラスタ化インデックス(プライマリ・キー・インデックス、PID)を形成し、B +ツリーインデックスは、ハード・ディスク上の実際のデータのリーフノードがあります。B +ツリーインデックスと非クラスタ化インデックス(非一意のインデックス、NUM)が形成されている他、そのリーフノードがまだiノード、NUM列フィールドの格納された値、および対応するクラスタ索引。
これは私を見てとることができ、「原則のMySQL(InnoDBの)インデックス」
次の分析が開始され
(1) select * from table where num = 200
いずれかのロックなしのスナップショットの読み取りです。
(2)select * from table where num > 200
任意ロックすることなく、それがスナップショットの読み取りです。
(3)select * from table where num = 200 lock in share mode
場合、インデックスレコード2の200に起因するインデックスNUM列にNUM = 200、第1ステージプラスラインNUM = Sロック。次に、クラスタ化インデックスは、ツリーを照会するために、PID = 2,7に対応するこれら二つのレコードは、このように現在の読み出しを使用して、クラスタ化インデックスPID = 2,7に行レベルのロックを適用S。
(4)select * from table where num > 200 lock in share mode
NUM> 200、行レベルの指標300のインデックスNUM列、第1予選NUM = Sプラスロックが記録されているので、場合。次に、クラスタ化インデックスは、ツリーを照会するために、PID = 3対応このレコード、クラスタ化インデックス3、現在の読み取りの使用にPID = Sのプラスラインレベルロックので。
(5)select * from table where num = 200 for update
場合によりインデックスNUM列にNUM = 200、ので、レベルXのNUMの最初の行=プラスインデックスレコード200上の2つのロック。次に、クラスタ化インデックスは、これらの二つのレコードがPID = 2,7対応するツリーを照会するので、現在のリードを使用して、PID = 2,7に行レベルロックのXにクラスタ化インデックスを追加します。
(6)select * from table where num > 200 for update
NUM> 200、行レベルの指標300のインデックスNUM列、第1予選NUM = Xプラスロックが記録されているので、場合。次に、クラスタ化インデックスは、ツリーを照会するために、PID = 3に対応し、このレコード、そうまた、PID = X行レベルのクラスタ化インデックス3で、電流の読み取りの使用。

RR /シリアライズ+条件は非索引付けされ

RRレベルは、より多くの配慮が関係なく、すべてのテーブル全体をロックチェック方法を、ここで彼のロック、ギャップロックではありませんが必要です。次の
次の分析が開始される
(1)select * from table where num = 200
任意ロックすることなく、スナップショットが読み出され、RRレベル。
直列化レベルでは、PID = 1,2,3,7 Sプラス(すべてのレコードの完全なリスト)にロッククラスタ化インデックス。そして
クラスタ化すべてのギャップは、インデックス(-∞、1)(1,2) (2,3)(3,7)(7、+∞)はロックGAPを添加した
(2)select * from table where num > 200
任意ロックすることなく、RRレベルで、それは、スナップショットの読みです。
直列化レベルでは、PID = 1,2,3,7 Sプラス(すべてのレコードの完全なリスト)にロッククラスタ化インデックス。そして
クラスタ化すべてのギャップは、インデックス(-∞、1)(1,2) (2,3)(3,7)(7、+∞)はロックGAPを添加した
(3)select * from table where num = 200 lock in share mode
PID = 1,2,3、InをS 7プラスロックオン(すべてのレコードの完全なリスト)クラスタ化インデックス。そして
クラスタ化すべてのギャップは、インデックス(-∞、1)(1,2) (2,3)(3,7)(7、+∞)はロックGAPを添加した
(4)select * from table where num > 200 lock in share mode
PID = 1,2,3、InをS 7プラスロックオン(すべてのレコードの完全なリスト)クラスタ化インデックス。そして
クラスタ化すべてのギャップは、インデックス(-∞、1)(1,2) (2,3)(3,7)(7、+∞)はロックGAPを添加した
(5)select * from table where num = 200 for update
PID = 1,2,3、InをX 7プラスロックオン(すべてのレコードの完全なリスト)クラスタ化インデックス。そして
クラスタ化すべてのギャップは、インデックス(-∞、1)(1,2) (2,3)(3,7)(7、+∞)はロックGAPを添加した
(6)select * from table where num > 200 for update
PID = 1,2,3、InをX 7プラスロックオン(すべてのレコードの完全なリスト)クラスタ化インデックス。
すべてのギャップクラスタ化インデックス(-∞、1)(1,2)(2,3)(3,7)(7、+∞)プラスギャップロック

RR /シリアライズ+条件クラスタ化されたインデックス

まあ、PIDを知っている必要があります誰もがそうPID使用は、クラスタ化インデックスで、主キー列です。これは、ことを特徴とするロックの場合、場合where条件は正確なクエリ(後=ケース)のみレコードロックが存在します。場合where範囲クエリ(条件>または<ケース)、レコードロック+ギャップロックがあります。
(1)select * from table where pId = 2
RRレベルの下で、任意ロックすることなく、それがスナップショットの読み取りです。
直列化レベルにおいて、電流が読み出され、PID = 2にインデックスをクラスタ化されたS-ロックを加え、ギャップロックは存在しません。
(2)select * from table where pId > 2
RRレベルでは、任意のロックがなければ、スナップショットの読み取りです。
直列化レベルにおいて、現在の読み出し、3,7のクラスタ化インデックスに加えて、PID = Sロック。(2,3)(3,7)(7 、+∞) プラスGAPをロック
(3)select * from table where pId = 2 lock in share mode
電流の読み取りであり、加えてS = 2のPIDにクラスタ化インデックスをロックし、隙間ロックは存在しません。
(4)select * from table where pId > 2 lock in share mode
現在の読み取りで、プラスSは、PID = 3,7にクラスタ化インデックスをロックします。(2,3)(3,7)(7においては 、+∞) プラスGAPをロック
(5)select * from table where pId = 2 for update
現在の読み取りに加え、クラスタ化インデックスPID = 2にXロックです。
(6)select * from table where pId > 2 for update
また、3,7のクラスタ化インデックスにPID = xで。(2,3)(3,7)(7 、+∞) プラスギャップロック
(7)select * from table where pId = 6 [lock in share mode|for update]
注意、PID = 6列が存在しない場合、これは上の(3,7)ギャップロックに追加されます。
(8)select * from table where pId > 18 [lock in share mode|for update]
の注目は、PID> 18は、クエリ結果は空です。この場合、上のギャップロック(7、+∞)で適用されます。

RR /シリアライズ+条件は、非クラスタ化インデックスです

ここで非クラスタ化インデックスには、一意のインデックスかを区別する必要があります。非一意索引場合、ロックをロックギャップが異なるからです。
私は状況固有のインデックスについてお話しましょう。ここで、一意のインデックスは、そして場合RR /シリアライズ+クラスタ化インデックス条件は同様の、唯一の違いは、ということである。この時点で2つの索引ツリーがあり、ロックは、対応する非クラスタ化インデックスツリーと木クラスタ化インデックスに適用されます!私たちは!自己吟味することができます
についての講演に続いて、非クラスタ化インデックスが非一意のインデックス、彼とインデックスの唯一の違いは、インデックスでのお問い合わせ後、だけでなく、レコードロック、ギャップロックがあり、正確です。そして、ユニークインデックスで正確な照会後、唯一のレコードロックがあり、ギャップロックは存在しません。古いルールは、非ユニーク索引列確立NUMでは
(1)select * from table where num = 200
任意のロックせずに、RRレベルでは、スナップショットの読みです。
直列化レベルでは、電流が読み取られ、Sに加え、クラスタ化PID = 2,7のインデックス、Sプラス非クラスタ(100,200)のインデックスNUM = 200(200,300)に加えてギャップロックのロックをロックします。
(2)select * from table where num > 200
RRレベルでは、任意のロックがなければ、スナップショットの読み取りです。
非クラスタ化インデックスにクラスタ化インデックス3、Sプラスロックに直列化レベル、現在の読み出し、加えてPID = SロックにNUM = 300です。(200,300)、(300、+∞で ) プラスGAPをロック
(3)select * from table where num = 200 lock in share mode
電流の読み取りであり、加えてSは、クラスタPID = 2,7のインデックス、Sプラス非クラスタインデックスNUM = 200でのロックをロック(100,200)(200,300)プラスギャップロック。
(4)select * from table where num > 200 lock in share mode
ロックNUM = Sでロックプラス非クラスタ化インデックス300に加えて、PID = S 3クラスタ化インデックスに、電流の読み取りです。(200,300)、(300、+∞で ) プラスギャップロック。
(5)select * from table where num = 200 for update
これは、現在の読み出し、プラスSロック非クラスタ化インデックスNUM = 200でクラスタ化インデックスPID = 2,7及びXプラスロックオン(100,200)で(200,300)プラスギャップロックです。
(6)select * from table where num > 200 for update
非クラスタ化インデックス300に付加NUM = Xで、ロック3にインデックスをクラスタ化付加のPID = Sに、電流の読み取りです。(200,300)、(300、+∞で ) プラスギャップロック
(7)select * from table where num = 250 [lock in share mode|for update]
注意、NUM = 250カラムが存在しない場合、これは上のギャップロック(200,300)に追加されます。
(8)select * from table where num > 400 [lock in share mode|for update]
の注目は、PID> 400は、クエリ結果は空です。この場合、ギャップロックがON(400、+∞)が印加されます。

おすすめ

転載: www.cnblogs.com/imike/p/11320138.html