InnoDBは、MySQLのデフォルトの分離レベルでファントムリードを解決します

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

  キーが来ています

  読んでみると、両方の条件が同時に満たされている必要があります

  1. 作成されたバージョンが現在のトランザクションのバージョン番号以下であることを読み取ります。これは、このトランザクションの前にデータが作成されたことを意味します
  2. バージョンが空であるか、現在のトランザクションバージョン番号より大きいレコードを削除します。つまり、このトランザクションの後に削除操作が発生します。

トランザクション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)が得られます

おすすめ

転載: www.cnblogs.com/cjjjj/p/12735495.html