ホームページ  >  記事  >  データベース  >  mysql の 4 種類の分離レベルについての深い理解

mysql の 4 種類の分離レベルについての深い理解

零下一度
零下一度オリジナル
2017-04-27 09:18:591297ブラウズ


SQL 標準では、トランザクション内外のどの変更が表示され、どの変更が不可視であるかを制限するいくつかの特定のルールを含む、4 種類の分離レベルが定義されています。一般に、分離レベルが低いほど高い同時実行性がサポートされ、システムのオーバーヘッドが低くなります。

Read Uncommitted (コミットされていないコンテンツの読み取り)

この分離レベルでは、すべてのトランザクションが他のコミットされていないトランザクションの実行結果を確認できます。この分離レベルは他のレベルと比べてパフォーマンスがそれほど優れていないため、実際のアプリケーションではほとんど使用されません。コミットされていないデータの読み取りは、ダーティ リードとも呼ばれます。
Read Committed

これは、ほとんどのデータベース システムのデフォルトの分離レベルです (ただし、MySQL のデフォルトではありません)。これは分離の単純な定義を満たしています。つまり、トランザクションはコミットされたトランザクションによって行われた変更のみを確認できます。この分離レベルは、いわゆる非反復読み取りもサポートします。これは、同じトランザクションの他のインスタンスがインスタンスの処理中に新しいコミットを持つ可能性があるため、同じ選択が異なる結果を返す可能性があるためです。
Repeatable Read (再読み取り可能)

これは、データを同時に読み取るときに、同じトランザクションの複数のインスタンスが同じデータ行を参照することを保証する、MySQL のデフォルトのトランザクション分離レベルです。ただし、理論的には、これはファントム リード (ファントム リード) という別のやっかいな問題につながります。簡単に言えば、ファントム読み取りとは、ユーザーが特定の範囲のデータ行を読み取るときに、別のトランザクションがその範囲に新しい行を挿入することを意味します。ユーザーがその範囲内のデータ行を読み取ると、新しい「ファントム」OK が存在することがわかります。 。 InnoDB および Falcon ストレージ エンジンは、マルチバージョン同時実行制御 (MVCC、Multiversion Concurrency Control) メカニズムを通じてこの問題を解決します。

Serializable
これは、トランザクションが互いに競合しないように強制的に順序付けすることで、ファントム読み取りの問題を解決します。つまり、読み取られた各データ行に共有ロックが追加されます。このレベルでは、多数のタイムアウトやロック競合が発生する可能性があります。

これらの 4 つの分離レベルは、異なるロック タイプを使用して実装されています。同じデータが読み取られると、問題が発生しやすくなります。例: Drity Read: 1 つのデータが更新され、この時点で別のトランザクションが同じデータを読み取ります。 何らかの理由で、前のロールバック操作、次に後のトランザクション、そして 1 つのトランザクションの順に読み取られたデータは正しくありません。

非反復読み取り (Non-repeatable read): トランザクションによって更新された元のデータが 2 つのクエリ プロセスの間に挿入されたことが原因である可能性があります。

たとえば、トランザクションの 2 つのクエリ内のデータ項目の数が一致していません。 1 つのトランザクションが複数のデータ行をクエリし、同時に別のトランザクションが後続のクエリで新しい列データ行を挿入します。前回のトランザクションでは、以前にはなかったデータ列がいくつかあることがわかります。

MySQL では、これら 4 つの分離レベルが実装されており、発生する可能性のある問題は次のとおりです:


次に、MySQL クライアント プログラムを使用して、いくつかの分離レベルをそれぞれテストします。テスト データベースは test で、テーブルは tx です。テーブル構造:

2 つのコマンド ライン クライアントは A と B で、A の分離レベルを常に変更し、B 側のデータを変更します。

(1) A の分離レベルをコミットされていない読み取りに設定します

B がデータを更新しない前:

クライアント A:

B がデータを更新:

クライアント B:

クライアント A:

上記の実験の後、トランザクション B はレコードを更新したと結論付けることができますが、この時点ではトランザクション B は送信されません。この時点で、トランザクション A はコミットされていないレコードをクエリできます。ダーティリードを引き起こします。コミットされていない読み取りは、最も低い分離レベルです。

(2) クライアント A のトランザクション分離レベルを読み取りコミットに設定します

B がデータを更新しない前:

クライアント A:

Bが更新されましたデータ:

クライアント B:

クライアント A:

上記の実験の後、送信されたと結論付けることができます。読み取り分離レベルは、つまり、2 つのクエリの間でトランザクション B がデータを更新したために、2 つのクエリのトランザクション A のデータが不一致になります。コミットされた読み取り専用では、コミットされたレコードの読み取りが許可されますが、反復可能な読み取りは必要ありません。

(3)、

A の分離レベルを反復読み取りに設定します

B がデータを更新しない前:

クライアント A:

B更新データ:

クライアント B:

クライアント A:

B データを挿入:

クライアント B:

クライアント A:

上記の実験から、反復可能な読み取り分離レベルではコミットされたレコードの読み取りのみが許可され、トランザクションがレコードを 2 回読み取る間、他のトランザクションがこのレコードを更新すると結論付けることができます。ただし、トランザクションは他のトランザクションとシリアル化できる必要はありません。たとえば、コミットされたトランザクションによって更新されたレコードをトランザクションが見つけることができる場合、ファントム読み取りの問題が発生する可能性があります (これは、データベースの分離レベルの実装が異なるために発生する可能性があることに注意してください)。上記のような実験では、データのファントムリードの問題は発生しません。

four)、aの分離レベルをa toserializablea-sideをセットしてトランザクションを開き、b-sideはレコードトランザクションa-を挿入します。側:

トランザクション B 側:

この時、トランザクション A の分離レベルはシリアライズ可能に設定されているため、トランザクション開始後はコミットされません。トランザクション B は待つことしかできません。

トランザクション A がトランザクションを送信します:

トランザクション A 側

トランザクション B 側

Serializable はフィールドを完全にロックします。トランザクションが同じデータをクエリする場合、前のトランザクションが完了してロックが解除されるまで待機する必要があります。 は完全な分離レベルであり、対応するデータ テーブルをロックするため、効率の問題が発生します。

id

以上がmysql の 4 種類の分離レベルについての深い理解の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。