1.まとめ
RRの分離レベルでは、InnodbはMVVCとネクストキーロックを使用してマジックリードを解決し、MVVCは通常の読み取り(スナップショットリード)のマジックリードを解決し、ネクストキーロックは現在の読み取り状況でマジックリードを解決します。
2.ファントムリーディングとは
トランザクションA、最初に実行:
テーブルセット名=“ hh”を更新します。ここでid> 3です。
結果は次のとおりです。
OK行xxテーブル名の成功によって影響を受けるデータの行数
トランザクションBは後で実行され、送信されます。
テーブルの値に挿入します(11、uu);
コミット;
トランザクションAを選択し、次を選択します。
id> 3のテーブルから*を選択
結果セットは次のとおりです。
…
11、彼
…
トランザクションAは無知です。それらすべてをid> 3で更新していませんか?
今回は、トランザクションAに対するコミットされたトランザクションBの影響です。この影響は「ファントム読み取り」と呼ばれます。
ファントムリーディングとノンリピータブルリーディングの違いは、前者は範囲であり、後者はそれ自体であることです
3.それを解決するには?
3.1。現在の読み
いわゆる現在の読み取りとは、ロックされた選択(SまたはX)、更新、削除、およびその他のステートメントを指します。RRトランザクション分離レベルでは、データベースは次のキーロックを使用して、このレコードとインデックス間隔をロックします。
上記の例では、RRの場合、現在の読み取りが使用され、ロックされた読み取り
select * from table where id> 3は、id = 3のレコードとid> 3の範囲をロックし、インデックスレコード間の範囲をロックし、範囲間のレコードの挿入を避け、幻の行レコードを避けます。
3.2。一般的な読み方
通常の読み取りはロックフリーの読み取りではないため、次のキーのロックは使用されません。魔法の読み取りを解決する方法はMVVCです
mvvcは、タプルの各行にいくつかの補助フィールドを追加し、作成バージョン番号を記録し、バージョン番号を削除します。
各トランザクションは、開始時に一意の増分バージョン番号を持っています。新しいトランザクションが開始されるたびに、トランザクションのバージョン番号がインクリメントされます。
デフォルトの分離レベル(REPEATABLE READ)では、追加と削除のチェックが次のように変更されます。
SELECT
は、現在のトランザクションバージョン番号以下の作成バージョンを読み取り、バージョンが空であるか、現在のトランザクションバージョン番号より大きいレコードを削除します。読み出しが存在する前に記録した本性を保証
INSERT
行のバージョン番号を作成するために、現在のトランザクションのバージョン番号を保存
UPDATE
元の記録ラインが、新たに挿入された行と行の新しいバージョンを作成するために、現在のトランザクションのバージョン番号削除バージョン番号は現在のトランザクションバージョン番号に設定されます
DELETE
は現在のトランザクションバージョン番号を行の削除されたバージョン番号に保存します
たとえば、レコードを挿入し、トランザクションIDが1であると想定した場合、レコードは次のようになります。つまり、作成バージョン番号はトランザクションバージョン番号です。
id |
名前 |
createversion |
deleteversion |
---|---|---|---|
1 | wxt | 1 |
更新すると、トランザクションIDは2と見なされます
id |
名前 |
createverison |
deleteversion |
---|---|---|---|
1 | wxt | 1 | 2 |
1 | Taotao | 2 |
ここでは名前をtaotaoに更新します。元のタプルの削除バージョン番号はこのトランザクションのIDであり、新しい
削除した場合、トランザクションがid = 3であると仮定します
id |
名前 |
createverison |
deleteversion |
---|---|---|---|
1 | Taotao | 2 | 3 |
キーが来ています
読んでみると、両方の条件が同時に満たされている必要があります
- 作成されたバージョンが現在のトランザクションのバージョン番号以下であることを読み取ります。これは、このトランザクションの前にデータが作成されたことを意味します
- バージョンが空であるか、現在のトランザクションバージョン番号より大きいレコードを削除します。つまり、このトランザクションの後に削除操作が発生します。
トランザクションAのIDが10であると想定します。
次に、テーブルセット名=“ hh”を更新します(id> 3の場合)。このステートメントを実行します
トランザクションB id = 11
テーブルの値に挿入します(11、uu);
最後のトランザクションA(id = 10)はここで読み込まれます
id> 3のテーブルから*を選択
上記のルールに従って、
作成されたバージョンが現在のトランザクション以下であることを読み取ります→→(4、a)(5、b)(4、hh)(5、hh)
上記のルールの出力が次のルールの入力として使用される場合
バージョンが空または現在のトランザクションのバージョン番号よりも大きいレコードを削除→(4、hh)(5、hh)
このようにして、トランザクションBの新しく挿入された行は読み取られず、魔法の読み取りが解決されます。
トランザクションBがタプル名= ccをID = 4で更新する場合
同様に、更新のルールに従って
次に、選択の規則に従って読んだ場合でも、(4、hh)(5、hh)が得られます