ホームページ  >  記事  >  データベース  >  MySQL がファントム読み取り問題をどのように解決するかを簡単に分析した記事

MySQL がファントム読み取り問題をどのように解決するかを簡単に分析した記事

青灯夜游
青灯夜游転載
2023-02-06 20:14:162059ブラウズ

MySQL はファントム リードの問題をどのように解決しますか?この問題については次の記事で解説していますので、疑問を持ちながら記事を読んでみましょう!

MySQL がファントム読み取り問題をどのように解決するかを簡単に分析した記事

## ジン・ブサンとイン・ブシの頻繁なインタビュー質問の中で、MySQL のトランザクション特性、分離レベル、その他の問題も、非常に古典的な 8 部構成のエッセイの 1 つです。この種の質問に直面すると、ほとんどの友人はこれに精通していると推定されます:

トランザクション特性 (ACID): Atomicity (Atomicity##) #)、分離(分離)、一貫性(一貫性)および永続性

分離レベル

: READ UNCOMMITTED(READ UNCOMMITTED), READ COMMITTED(READ COMMITTED), Repeatable Read (REPEATABLE READ)、 Serializable (SERIALIZABLE) そして、それぞれの種類の分離 レベルによって引き起こされる問題は次のとおりです。 :

    READ UNCOMMITTED
  • 分離レベルでは、ダーティ読み取り非反復読み取りおよび##が発生する可能性があります。 #phantom readproblemREAD COMMITTED
  • 分離レベルでは、
  • non-repeatable read および phantom read の問題が発生する可能性がありますが、これらは問題です。不可能です ダーティ リード問題REPEATABLE READ
  • 分離レベルでは、
  • ファントム リード問題が発生する可能性がありますが、ダーティ リード#は発生しません## および Non-repeatable read問題SERIALIZABLE分離レベルでは、さまざまな問題は発生しません
  • MySQL InnoDB の場合ストレージ エンジンでサポートされるデフォルトの分離レベルは REPEATABLE-READ (反復可能)
  • です。上記の SQL 標準の 4 つの分離レベルの定義から、
REPEATABLE-READ (反復可能)

となります。 ファントム リード を防ぐことは不可能ですが、MySQL InnoDB ストレージ エンジンがファントム リードの問題を解決することは誰もが知っています。では、どのようにしてそれを解決するのでしょうか? 1. 行フォーマット

本題に入る前に、まず行フォーマットとは何かを一般的に理解すると、次の MVCC を理解するのに役立ちます。行フォーマットは、テーブル内の行レコードがディスクに保存される方法です。Innodb ストレージ エンジンには、合計 4 つの異なるタイプの行フォーマットがあります:

compact

redundant , dynamic , compress; 行フォーマットには多くの種類がありますが、原理的には基本的に同じで、次のように、 compact 行フォーマット: As図からわかるように、完全なレコードは実際には 2 つの部分に分けることができます: 記録された追加情報 記録された実際のデータ MySQL がファントム読み取り問題をどのように解決するかを簡単に分析した記事. 記録された追加情報 はそれぞれ changes. 長いフィールド長リスト NULL 値リスト および レコード ヘッダー情報 、および 記録された実際のデータ 独自に定義した列に加えて、 MySQL は、各レコードにいくつかのデフォルトの列を追加します。これらのデフォルトの列は、隠し列とも呼ばれます。特定の列は次のとおりです:

列名Lengthrow_id6 バイト 6 バイトを識別します7 バイト
Description
一意の行 ID 1 つの Record transaction_id
トランザクション ID roll_pointer
ロールバック ポインタ

非表示列の値について心配する必要はありません。 InnoDB ストレージ エンジンがそれを生成します。さらに詳細に描画しましょう。 compact行形式は次のとおりです:

MySQL がファントム読み取り問題をどのように解決するかを簡単に分析した記事

  • transaction_id: トランザクション ID トランザクションが行レコードを変更すると、このトランザクションのトランザクション ID がこの列に割り当てられます。
  • ##roll_pointer: 行が変更されるたびにレコードが変更されると、古いバージョンのデータが undolog ログに書き込まれます。
  • 続いて、roll_pointerundolog を指します。 なので、この列はポインターに相当し、これを介して「前の情報の変更」

#2. MVCC の詳細な説明

# を見つけることができます。 #2.1 バージョン チェーン

次のようなレコードがあるとします。

レコードに挿入された

トランザクション IDMySQL がファントム読み取り問題をどのように解決するかを簡単に分析した記事80 であり、roll_pointer ポインタは NULL です (理解を容易にするため、読者はポインタが NULL であることを理解できます。実際は roll_pointer 最初のビットは、それが指す Undo ログのタイプをマークします。このビットの値が 1 の場合、それは意味します。これが指す undo ログ タイプが insert undo であることを示します)次の 2 つを仮定します

トランザクション ID

100200 のトランザクションがそれぞれ実行されますこのレコードに対する UPDATE 操作: <pre class="brush:js;toolbar:false;"> -- 事务id=100 update person set grade =20 where id =1; update person set grade =40 where id =1; -- 事务id=200 update person set grade =70 where id =1;</pre> レコードが変更されるたびに、

元に戻すログ

が記録されます。各 元に戻すログ roll_pointer 属性 (操作に対応する INSERT) もあり、レコードには以前のバージョンがないため、##undo log にはこの属性がありません)、次のようにすることができます。これらの undo log をリンク リストに接続すると、現在の状況は下の図のようになります。 同じ: レコードが更新されるたびに、古い値が配置されます

undo ログ

、古いバージョンのレコードであっても、更新の数が増えると、すべてのバージョンが MySQL がファントム読み取り問題をどのように解決するかを簡単に分析した記事roll_pointer 属性によってリンク リストに接続されます。このリンク リストを バージョン チェーン と呼びます。バージョン チェーンのヘッド ノードは、現在のレコードの最新の値です。さらに、各バージョンには、対応する transaction id#2.2 ReadView

# データベースの 4 つの分離レベル: 1) read uncommitted

; 2)

read committed; 3) REPEATABLE READ; 4)SERIALIZABLE; たとえば、READ UNCOMMITTED 、毎回バージョン チェーンの最新データを読み取るだけです; SERIALIZABLE、主にロックによって制御されます; read commitREPEATABLE READ これらはすべて、これら 2 つの分離レベルでは、バージョン チェーン内のどのものが現在のものに表示されるかが中心的な問題になります。この問題を解決するために、MySQL は読み取りビューの概念を提案しました。これには 4 つの中核的な概念が含まれています。 m_ids

:
    read view
  • を生成するとき、アクティブなモノ ID コレクション min_trx_id:# # の最小値#m_ids
  • 、つまり、読み取りビューを生成するときのアクティブなものの最小値
  • max_trx_id: 読み取りビュー
  • を生成するときに、システムが次のモノの ID 値
  • creator_trx_id を割り当てる必要があります。これは、read view
  • を作成するモノの ID (現在のモノの ID) です。
  • このReadViewを使用すると、レコードにアクセスするときに、次の手順に従うだけで、レコードの特定のバージョンが表示されているかどうかを確認できます。
記録されたモノの ID が

creator_trx_id と等しい場合、現在のモノが変更したレコードにアクセスしていることを意味するため、このバージョンは表示されますMySQL がファントム読み取り問題をどのように解決するかを簡単に分析した記事アクセスされたバージョンの場合Thing ID が

min_trx_id
    より小さい場合、
  • read view が作成されたときに Thing が送信され、このバージョンが現在の Thing に読み取り可能であることを意味します
  • Ifアクセスされたモノのバージョン ID が
  • max_trx_id 以上の場合、read view が作成されるときに、バージョン レコードを生成するモノ ID が開かれていないことを意味しますRead view
  • が生成されるまで、このバージョンは現在の Thing
  • で読み取ることができません。アクセスされたバージョンの Thing transaction_idm_ids# にある場合、 ## コレクションの場合、Read view が生成された時刻、トランザクションがまだアクティブで送信されていない場合、バージョンにアクセスできないことを意味します。そうでない場合は、バージョンを生成したトランザクションを意味します。
  • ReadView
  • は作成され、送信され、アクセスできます 注: 読み取り用の ID は 0 です

    MySQL では、READ COMMITTEDREPEATABLE READ 分離レベルの大きな違いは、異なるタイミングで ReadView を生成することです。

    • READ COMMITTED —— ReadView
    • REPEATABLE READ を生成します —— 毎回データを読み取る前に、データを 1 回読み取るときに、 ReadView
    が生成されます。詳細な例を使用して 2 つの違いを説明しましょう:

    Timenumbertrx 100trx 200①BEGIN; #②③④SELECT * FROM person WHERE id = 1;##個人セットのグレード =70 (ID =1) を更新します。SELECT * FROM person WHERE id = 1;コミット;コミット;trx 100時間⑥では、トランザクション trx 200




    BEGIN;
    BEGIN;

    個人セットのグレード =20 (ID = 1) を更新します;

    ##個人セットのグレード =40 (ID =1) を更新します;



    ##コミット;




    9


    ?

    ##時刻④では、トランザクション
    によりトランザクションが送信され、id=1 行に記録されているバージョン チェーンは次のようになります。
    により、トランザクションのコミットが実行され、バージョン チェーンが id=1 行に記録されます。 次のように:

    時間 ⑤ では、トランザクション MySQL がファントム読み取り問題をどのように解決するかを簡単に分析した記事trx 100 は、select

    ステートメントの実行時に最初に

    ReadView## を生成します。 MySQL がファントム読み取り問題をどのように解決するかを簡単に分析した記事ReadView

    m_ids リストの [100, 200]min_trx_id100 max_trx_id201creator_trx_id0 です。この時点では、バージョン チェーンから表示されているレコードを選択し、バージョン チェーンを上から下までたどります。下: Grade=40 であるため、trx_id の値は m_ids にある 100 であるため、レコードは表示されません。 =20も見えません。引き続き下に移動し、グレード = 20、trx_id 値は 80 であり、ReadViewmin_trx_id100# よりも小さいです。 ## したがって、このバージョンは要件を満たしており、レベル 10 のレコードがユーザーに返されます。 時間 ⑧ で、トランザクションの分離レベルが READ COMMITTED の場合、別の ReadView (ReadView# の ##) が生成されます。 m_ids リストの内容は [200]

    min_trx_id200max_trx_id 201 , creator_trx_id0 です。このとき、バージョン チェーンから表示されているレコードを選択すると、バージョン チェーンが上から下にたどられます: Grade=70 であるため、 trx_id の値は m_ids200 であるため、レコードは表示されません。トラバースを続けます。grade=40、trx_id値は 100 です。これは ReadViewmin_trx_id200 より小さいため、このバージョンは要件を満たしており、レコードは次のようになります。レベル 40 がユーザーに返されます。 時間 ⑧ で、トランザクションの分離レベルが REPEATABLE READ である場合、時間 8 で、ReadView は個別に生成されず、時間ごとに生成されます。 ReadView では 5 が使用されるため、ユーザーに返されるレベルは 10 です。 2 つの選択の結果は同じです。これが 繰り返し読み取り の意味です。

    3. 概要 MVCC の詳細な説明を分析すると、MVCC に基づいて、RR 分離レベルの下で、非常に簡単に解決できると結論付けることができます。 ファントム読み取り問題ですが、select for update が現在の読み取りを生成し、スナップショット読み取りではなくなっていることがわかっています。この場合、MySQL は ファントム読み取り

    をどのように解決しますか?問題?時間の問題 (整理して図を描くにはかなりの時間がかかります) に基づいて、最初に結論を述べてから、現在の読み取り状況で MySQL が

    ファントム読み取り 問題をどのように解決するかを分析します。

    現在の読み取り値: Next-Key Lock (ギャップ ロック) を使用して、ファントム読み取りが発生しないようにロックします。ギャップ ロックの使用方法現在の読書状況 ファントム リーディングの問題を解決したい場合は、興味のある友人がフォローといいねを追加してください [関連する推奨事項: mysql ビデオ チュートリアル

    ]

    以上がMySQL がファントム読み取り問題をどのように解決するかを簡単に分析した記事の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

    声明:
    この記事はjuejin.cnで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。