[MySQLスタディノート(18)]トランザクション分離レベル、MVCC、パージ

この記事は公式アカウント[DevelopingPigeon]から公開されています!フォローへようこそ!


古いルール-姉妹都市都市:

1。トランザクション分離レベル

(I.概要

        MySQLはC / Sアーキテクチャソフトウェアであるため、同じサーバーに対して複数のクライアントを接続できます。各クライアントがサーバーに接続した後、セッションが形成され、各クライアントは独自のセッションに参加できます。 requestの場合、requestステートメントは特定のトランザクションの一部である可能性があり、サーバーは複数のクライアントからの複数のトランザクションを同時に処理できます。トランザクションは実世界の状態遷移に対応するため、トランザクションの実行後、データが実世界のルールに準拠していることを確認する必要があります。これがトランザクションの一貫性です。

        同じデータに同時にアクセスしたいトランザクションが複数ある場合は、何らかの方法でこれらのトランザクションを1つずつ順番に個別に実行する必要があります。そうしないと、最終的な実行結果は個別の実行と同じになります。 、各トランザクションは分離して実行され、相互に干渉しない、これは問題の分離です。最も簡単な方法は、順番に実行し、すべてのトランザクションを単一のスレッドで直接実行することです。この方法はシリアル実行と呼ばれ、非効率的です。トランザクションが特定のデータにアクセスする場合やその他の試行に制限することもできます。同じデータトランザクションにアクセスすることは制限され、キューに入れられます。この方法はシリアル化可能な実行と呼ばれます。


(2)トランザクションの同時実行性の一貫性

        ダーティ書き込みとダーティ読み取りは一緒に記憶されます.1つはコミットされていないトランザクションによって変更されたデータを書き込むことで、もう1つは読み取りです。繰り返し不可能な読み取りとファントム読み取りは一緒に記憶され、どちらもコミットされていないトランザクションによって読み取られたデータを変更します。

1.汚い文章

        トランザクションが、コミットされていない別のトランザクションによって変更されたデータを変更する場合、それはダーティライト現象と呼ばれます。記憶を理解する方法は?ダーティは、コミットされていないトランザクションによって変更されたデータを表し、書き込みは、別のトランザクションによるデータの変更を表します。1つのトランザクションがこのデータを変更し、別のデータがこのデータを変更すると、2つのトランザクションの最終結果が異なります。

2.ダーティリード

        トランザクションが別のコミットされていないトランザクションによって変更されたデータを読み取る場合、それはダーティ読み取り現象と呼ばれます。厳密な解釈では、T1トランザクションは最初にデータの値を変更し、次にT2トランザクションはコミットされていないトランザクションT1のxの変更された値を読み取り、次にT1はT2送信を中止し、T2は存在しない値を読み取ります。

3.繰り返し不可能な読書

        トランザクションが別のコミットされていないトランザクションによって読み取られたデータを変更する場合、それは繰り返し不可能な読み取りが発生したことを意味します。つまり、トランザクションは、別のトランザクションが変更される前後に、同じデータに対して異なる結果を読み取ります。

4.ファントムリーディング

        トランザクションが特定の検索条件に基づいて最初にいくつかのレコードを照会した場合、トランザクションがコミットされなかったときに、別のトランザクションがそれらの検索条件を満たすいくつかのレコード(INSERT、UPDATE、DELETE)を書き込んだ場合、ファントム読み取りが動作していることを意味します。前のトランザクションが再度検索されたとき、結果が最初の検索と矛盾していたためです。この概念は繰り返し不可能な読み取りに似ているように見えますが、ファントム読み取りはレコードを検索するためのものであり、繰り返し不可能な読み取りはレコードを読み取るためのものです。

(3)SQL標準の4つの分離レベル

        上記の4つの整合性問題の重大度の順序は次のとおりです。

脏写 > 脏读 > 不可重复读 > 幻读

        シリアル実行の最高の分離方法の場合、結果は最悪のパフォーマンスになります。パフォーマンスの一部と引き換えに分離を放棄することができます。これは、分離レベルを確立する本来の目的です。分離レベルが高いほど、問題は少なくなり、パフォーマンスは低下します。分離レベルが低いほど、問題が多くなり、パフォーマンスが向上します。

1.コミットされていない読み取り

        分離レベルが最も低いと、ダーティリード、繰り返し不可能なリード、ファントムリードなど、ほとんどの問題が発生する可能性があります。文字通りの意味から、コミットされていないトランザクションのデータを読み取る機能はダーティ読み取りです。ダーティ読み取りでも問題を解決することはできません。後でそれほど深刻ではない問題は言うまでもありません。

2.提出済み

        ダーティリーディングの問題を解決し、繰り返し不可能なリーディングとファントムリーディングが発生する可能性があります。文字通りの観点から、コミットされたトランザクションのデータを読み取る機能は、ダーティ読み取りの問題が解決されたことを示し、フォローアップの問題があります。

3.繰り返し読む

        ダーティリーディング、繰り返し可能なリーディング、およびファントムリーディングの可能性の問題を解決します。


4.シリアル化可能

        ダーティリーディング、リピーターブルリーディング、ファントムリーディングの問題を解決します。これは、最も強力な分離と最も低いパフォーマンスで、シリアル化可能な方法で実行されます。

        ダーティライティングの問題について、すべての分離レベルが言及されていないのはなぜですか?ダーティ書き込みは整合性に深刻な影響を与えるため、どの分離レベルでもダーティ書き込みが発生しないようにします。


(4)Mysqlでサポートされる4つの分離レベル

        データベースベンダーが異なれば、SQL標準の4つの分離レベルのサポートも異なります。MySQLは4つのレベルをサポートしていますが、繰り返し可能な読み取りレベルでは、ファントム読み取りを大幅に禁止できます。デフォルトレベルは繰り返し可能な読み取りです。

1.トランザクションの分離レベルを設定します

set global transaction isolation level serializable;

        グローバルスコープに影響を与え、ステートメントが実行された後のセッションにのみ影響を与えるsetキーワードの後に​​globalキーワードを配置します。これは、現在存在するセッションでは無効です。

set session transaction isolation level serializable;

        setキーワードの後に​​sessionキーワードを置きます。これは、セッションのスコープ内で有効であり、現在のセッションの後続のすべてのトランザクションで有効です。

        どちらのキーワードも使用されていない場合、現在のセッションで開かれる次のトランザクションに対してのみ有効であり、後続のトランザクションは前の分離レベルに復元されます。

2.サーバーのデフォルトの分離レベルを変更します

        スタートアップ項目transaction-isolationを変更するか、システム変数transaction_isolationを変更します。このシステム変数には、GLOBAL、SESSIONの3つのスコープがあり、次のトランザクションのみが対象です。

SET GLOBAL transaction_isolation=…
SET SESSION var_name = xxx
SET var_name = xxx

二。MVCC

(1)バージョンチェーン

        InnoDBストレージエンジンを使用するテーブルの場合、そのクラスター化インデックスレコードには2つの必要な非表示列が含まれます。trx_id属性はレコードを変更するトランザクションIDを表し、roll_pointerはレコードが最後に変更された元に戻すログを指します。レコードの変更されたUNDOログは、バージョンチェーンと呼ばれるリンクリストにチェーンできます。バージョンチェーンのヘッドノードは、現在のレコードの最新の値であり、レコード変更前の情報を見つけることができます。

        さらに、各バージョンノードは、バージョンが生成されるときに対応するトランザクションIDも保存します。このレコードのバージョンチェーンを使用して、同じレコードにアクセスする同時トランザクションの動作を制御します。このメカニズムは、マルチバージョン同時実行制御(MVCC)と呼ばれます。 )。


(二)ReadView

        異なる分離レベルの場合、トランザクションは異なるバージョンのレコードを読み取ることができます。主要な問題は、バージョンチェーン内のどのバージョンが現在のトランザクションに表示されるかをどのように判断するかです。InnoDBは、ReadView(一貫性のあるビュー)を使用してこの問題を解決します。ビューには4つの重要なコンテンツがあります。

1. m_ids

        ReadViewを生成するとき、現在のシステムでアクティブな読み取りおよび書き込みトランザクション、つまりコミットされていないトランザクションのトランザクションIDリスト。

2. min_trx_id

        ReadViewが生成されるとき、現在のシステムのアクティブな読み取りおよび書き込みトランザクションの中で最小のトランザクションIDは、m_idsの最小値です。

3. max_trx_id

        ReadViewを生成するとき、システムは次のトランザクションのトランザクションIDを割り当てる必要があります。

4.creator_trx_id

        ReadViewを生成したトランザクションのトランザクションID。

(3)ReadViewに従って現在のレコードバージョンの可視性を判断する

        1.アクセスされたバージョンのtrx_id属性値がReadViewのcreator_trx_idと同じである場合、現在のトランザクションが変更したレコードにアクセスし、このバージョンのすべてのレコードに現在のトランザクションでアクセスできることを意味します。

        2.アクセスされたバージョンのtrx_id属性がReadViewのmin_trx_id属性よりも小さい場合、このバージョンのテーブル名を生成したトランザクションは現在のトランザクションの前にコミットされているため、現在のトランザクションからこのバージョンにアクセスできます。

        3.アクセスされたバージョンのtrx_id属性値がReadViewのmax_trx_id値以上の場合、このバージョンのテーブル名を生成したトランザクションは、現在のトランザクションがReadViewを生成した後に開始されるため、このバージョンにアクセスすることはできません。現在のトランザクション。

        4.アクセスされたバージョンのtrx_id属性値がReadViewのmin_trx_idとmax_trx_idの間にある場合、trx_id属性がm_idsリストにあるかどうかを判断する必要があります。ある場合は、このバージョンを生成したトランザクションがアクティブである必要があり、コミットされていないため、このバージョンを訪問することはできません。そうでない場合は、訪問することができます。

        特定のバージョンのデータが現在のトランザクションに表示されない場合は、バージョンチェーンに従って次のバージョンのデータを見つけ、上記の手順を実行してレコードの表示を確認します。最後のバージョンのページが表示されない場合表示されている場合、クエリ結果にはレコードが含まれていません。


(4)ReadViewを生成するタイミング

        送信された読み取り分離レベルは、毎回データを読み取る前にReadViewを生成します。つまり、ReadViewを継続的に更新します。現在のトランザクション送信ステータスに従って、ReadView内のトランザクションアクティブリストとその他のパラメーターを更新します。これにより、 currentトランザクション内の各読み取りの結果は異なる場合があります。これは、繰り返し不可能な読み取りの問題です。

        繰り返し可能な読み取り分離レベルの場合、クエリステートメントが最初に実行されたときにReadViewのみが生成され、最初のReadViewが毎回再利用されるため、トランザクションのアクティブリストやその他のパラメーターは変更されず、現在のトランザクションはバージョンチェーンから読み取られた結果はすべて一貫しており、繰り返し不可能な読み取りの問題を解決します。


(5)セカンダリインデックスとMVCC

        以前の検索は、クラスター化インデックスレコードの主キーに基づいています。クエリステートメントでセカンダリインデックスを使用してクエリを実行する場合、可視性を判断するにはどうすればよいですか。

次のように実行します。

        1.セカンダリインデックスページのページヘッダーに属性があります。ページ内のレコードが追加、削除、または変更されるたびに、操作を実行するトランザクションのトランザクションIDが属性の値より大きい場合、その値はトランザクションIDとして更新されます。これは、この属性がセカンダリインデックスページを変更する最大のトランザクションIDを表すことを意味します。SELECTステートメントがセカンダリインデックスレコードにアクセスするときは、最初に、現在のReadViewのmin_trx_idがページの属性値より大きいかどうかを確認します。大きい場合は、属性に対応するトランザクションが送信され、ページのすべてのレコードが送信されます。 ReadViewに関連するものは表示されます。そうでない場合は、テーブルに戻って実行し、表示を判断する必要があります。

        2.主キーを使用してテーブルに戻った後、対応するクラスター化インデックスを取得し、前の方法に従って最初に表示されるバージョンを見つけ、このバージョンの対応するセカンダリインデックス列の値がセカンダリインデックス列はクエリに使用されます値は同じです。はいの場合、レコードをクライアントに送信し、そうでない場合はスキップします。


三。パージについて

        挿入取り消しログはトランザクションがコミットされた後に解放でき、更新取り消しログもMVCCをサポートする必要があり、すぐに削除できないと言われていました。トランザクションによって書き込まれた取り消しログのグループに履歴リンクリストノードがあります。トランザクションがコミットされると、このトランザクションの実行中に生成された一連の更新取り消しログが、履歴リンクリストの先頭に挿入されます。これらの更新元に戻すログのスペースはいつ解放する必要がありますか?

        更新の取り消しログを完全に削除し、必要に応じて削除のマークが付けられたレコードのみを削除する必要があります。この操作はパージと呼ばれます。これらのログはMVCC用に保存されるため、システム内の最初のReadViewがログにアクセスしなくなる限り、ログの使命は終了します。ReadViewの生成時にトランザクションがコミットされていることを確認する限り、ReadViewはトランザクションの変更履歴の最新バージョンをすでに表示できるため、ReadViewはトランザクション中に生成された元に戻すログにアクセスする必要はありません。

        トランザクションがコミットされると、トランザクションnoという名前の値がトランザクションに対して生成され、トランザクションが送信された順序を示します。履歴リンクリストは、トランザクションが送信された順序で元に戻すログも配置します。 ReadViewには、現在よりも多く含まれます。システム内の最大のトランザクション番号も1より大きくなります。システム内のすべてのReadViewは、作成時間に従ってリンクリストに接続されます。パージ操作が実行されると、システムで生成された最初のReadViewが取り出されます。ReadViewがない場合は、新しいReadViewが作成され、次に小さいトランザクションの値は、履歴リンクリストから取り出されません。グループの取り消しログ。取り消しログのグループのトランザクションの値が最初のReadViewより小さい場合、それらのスペースは解放されます。

        ここで、繰り返し可能な読み取り分離レベルの場合、元のReadViewは常に再利用され、トランザクションは長期間実行されて送信されていないため、最初に生成されたReadViewは解放されず、システムの更新元に戻すログはますます多くなります。システムのパフォーマンスを無駄にしすぎます。

おすすめ

転載: blog.csdn.net/Mrwxxxx/article/details/114041800