MySQL トランザクション分離レベルとダーティ リード、ファントム リード、非反復読み取りの例

coldplay.xixi
リリース: 2021-01-06 09:40:35
転載
2491 人が閲覧しました

MySQL トランザクション分離レベルとダーティ リード、ファントム リード、非反復読み取りの例

推奨 (無料): mysql ビデオ チュートリアル

トランザクションの分離Property

MySQL はクライアント/サーバー アーキテクチャ ソフトウェアです。同じサーバーに対して、複数のクライアントが接続できます。各クライアントがサーバーに接続された後、それをセッションと呼びます。各クライアントは、独自のセッションでサーバーにリクエスト ステートメントを発行できます。リクエスト ステートメントはトランザクションの一部である場合があります。つまり、サーバーは複数のトランザクションを同時に処理する場合があります。データベース上で複数のトランザクションが同時に実行されると、ダーティリード、ノンリピータブルリード、ファントムリードなどの問題が発生することがあります。これらの問題を解決するために「分離レベル」という概念があります。

理論的には、トランザクションが特定のデータにアクセスする場合、他のトランザクションはキューに入れられる必要があります。トランザクションが送信された後でのみ、他のトランザクションはデータにアクセスし続けることができます。しかし、一般的に言えば、絶縁が厳しくなるほど効率は低下します。したがって、多くの場合、分離と効率の間のバランスを見つける必要があります。

同時トランザクション実行で発生する問題

ダーティ リード: ダーティ リードとは、あるトランザクションが、そのトランザクションによって変更されたコミットされていない別のデータを読み取ることを意味します。

たとえば、Xiao Wang の口座の残高が 100 の場合、Xiao Wang の口座にアクセスするには 2 つのトランザクションが必要になります。

##begin;#更新 xxx 残高 = 残高 50 を設定 ここで client_no = 'Xiao Wang クライアント番号' ;rollback;commit; 上記のように、セッション A とセッション B がそれぞれトランザクションを開始し、最初にセッション A が Xiao Wang のアカウントに残高を追加しました。 50. この時点で、アカウント B は Xiao Wang のアカウント残高を 150 としてクエリします。その後、セッション A がロールバックされ、セッション B によってクエリされた 150 は不正なダーティ データになります。
# セッション A セッション B

begin;
##selectbalance from xxx where client_no = 'Xiao Wang クライアント番号' ;
(150 と表示された場合は、ダーティ リードが発生したことを意味します)

非反復読み取り:

非反復読み取りとは、同じトランザクション内で同じデータ セットを複数回読み取ることを指しますが、結果は異なります。反復不可能な読み取りは、クエリされたデータが複数の検索中に他のトランザクションによって変更されたために発生します。

次の 2 つのセッション リクエストを見てください。

# セッション A セッション B##begin;begin;#更新 xxx 残高 = 残高 50 を更新 ここで client_no = 'Xiao Wang クライアント番号' ; セッション中A の同じトランザクション内で、2 つの同一のクエリの結果が異なります。これは、反復不可能な読み取りが発生したことを意味します。 ファントム読み取り: いわゆるファントム読み取りとは、トランザクションが特定の範囲のレコードを読み取るときに、別のトランザクションがその範囲にレコードを挿入することを意味します。再度範囲を指定すると、以前に読み取られなかったデータが読み取られます。
#クライアント番号 = 'Xiao Wang 顧客番号' の xxx から残高を選択 ;
(残高は 100 であると読み取ります)


##commit;
selectbalance from xxx where client_no = 'Xiao Wang クライアント番号' ;
(150 と表示された場合は、反復不可能な読み取りが発生したことを意味します) )

コミット;


現在、アカウント テーブル内の Xiao Wang の残高のみが 100 であると仮定し、次の 2 つのセッション リクエストを見てください。

# セッション A

セッション B

#残高 = 100 の xxx から名前を選択;(名前は「シャオ ワン」と読みます)begin;select name from xxx Balance where = 100;(「小王」と「小王」を読んだ場合張'、それはファントム リーディングが発生したことを意味します)#コミット;
##begin;


insert into xxx(client_no,name,balance) value('Xiao Zhang 顧客番号','Xiao Zhang',100);
#commit;



セッションの 2 番目のクエリトランザクションで、最初のクエリでは見つからなかった名前「Xiao Zhang」が見つかりました。これは、ファントム読み取りが発生したことを意味します。

SQL 標準によって確立された 4 つの分離レベル

ISO および ANIS SQL 標準では、次の 4 つのトランザクション分離レベルが確立されています。コミット済み (コミットされた読み取り)、反復可能読み取り (反復可能読み取り)、およびシリアライズ可能 (シリアル化可能)。

まず、これら 4 つの分離レベルの意味を見てみましょう。

  • Read uncommitted: トランザクションが送信されていない場合、トランザクションが行った変更は他のトランザクションから参照できます。
  • 読み取りコミット: トランザクションがコミットされると、その変更は他のトランザクションによって認識されます。
  • 反復読み取り: トランザクションの実行中に表示されるデータは、トランザクションの開始時に表示されるデータと常に一致します。もちろん、反復可能な読み取り分離レベルでは、コミットされていない変更も他のトランザクションからは見えません。
  • シリアル化: 名前が示すように、レコードの同じ行に対して、「書き込み」は「書き込みロック」を追加し、「読み取り」は「読み取りロック」を追加します。読み取り/書き込みロックの競合が発生した場合、後でアクセスされるトランザクションは、実行を続行する前に、前のトランザクションの完了を待つ必要があります。

SQL 標準では、分離レベルが異なると、同時トランザクションによってさまざまな重大度の問題が発生する可能性があると規定されています。具体的な状況は次のとおりです:
(√ は発生する可能性があることを意味します。× は発生する可能性があることを意味します)発生することはありません 発生しました)

##コミットされた読み取り#√√繰り返し読み取り)×√シリアライズ可能)
分離レベル ダーティ リード Non-Repeatable Read Phantom読み取り
コミットされていない読み取り
##× × ×
MySQL の 4 つの分離レベルのサポート

ISO および ANIS SQL 標準では 4 つのトランザクション分離レベルが規定されていますが、すべてのデータベース ベンダーがこれに従っているわけではありません。たとえば、Oracle データベースは、コミットされていない読み取り (コミットされていない読み取り) および反復可能な読み取り (反復可能な読み取り) トランザクション分離レベルをサポートしていません。

MySQL InnoDB ストレージ エンジンは 4 つの分離レベルをサポートしますが、SQL 標準で定義されているものとは異なります。

InnoDB ストレージ エンジンは、デフォルトの反復読み取り (反復読み取り) トランザクション分離レベル - Key Lock ロックで Next を使用します。アルゴリズムにより、ファントム読み取り

の発生が回避されます。言い換えれば、InnoDB ストレージ エンジンは、反復読み取りのトランザクション分離レベルの下でトランザクションの分離要件を完全に保証できます。つまり、SQL 標準のシリアル化可能な分離レベル要件に達しています。

トランザクション分離レベルの設定方法

InnoDB ストレージ エンジンでは、次のコマンドを使用して、グローバルまたは現在のセッションのトランザクション分離レベルを設定できます。

SET [GLOBAL|SESSION] TRANSACTION ISOLATION LEVEL{	READ UNCOMMITTED
	| READ COMMITTED
	| REPEATABLE READ
	| SERIALIZABLE}
ログイン後にコピー

現在のセッションの分離レベルを読み取りコミットに設定したい場合は、次のステートメントを使用できます。

SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
ログイン後にコピー

トランザクションのデフォルトの分離レベルを設定したい場合は、 MySQL データベースが起動されると、設定ファイル内のトランザクションを変更する必要があります。分離の値、たとえば、起動前に

transaction-isolation = READ COMMITTED

を指定した場合、デフォルトの分離レベルは、トランザクションは元の REPEATABLE READ から READ COMMITTED に変更されます。 現在のセッションのトランザクション分離レベルを表示するには、次のステートメントを使用できます:

SELECT @@transaction_isolation;
ログイン後にコピー

グローバル トランザクション分離レベルを表示するには、次のステートメントを使用できます:

SELECT @@global.transaction_isolation;
ログイン後にコピー

注:transaction_isolation は、tx_isolation を置き換えるために MySQL 5.7.20 で導入されました。以前のバージョンの MySQL を使用している場合は、上記のtransaction_isolation を tx_isolation に置き換えてください。

プログラミング関連の知識について詳しくは、

プログラミング ビデオ

をご覧ください。 !

以上がMySQL トランザクション分離レベルとダーティ リード、ファントム リード、非反復読み取りの例の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ソース:csdn.net
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート