MySQL トランザクション分離レベルの原則例分析

MySQL トランザクション分離レベルの原則例分析

導入

あなたも面接でこれに遭遇したことがあるはずです。

トランザクションの分離レベルについてお話ししましょう。

正直に言うと、トランザクション分離レベルに関する質問は、キャンパス リクルートメントであれソーシャル リクルートメントであれ、面接官が好んで聞く質問です。しかし、正直に言うと、インターネットで多くの記事を読んでみると、著者がそれらを理解しているかどうか疑問に思います。なぜなら、繰り返し読み取り (Repeatable Read) とシリアル化可能 (serializable) の分析が本当に混乱するからです。

また、「MySQL Technology Insider - InnoDB Storage Engine」など、多くの書籍では、繰り返し読み取りがファントム読み取り問題を解決すると書かれていますが、一々記載されていません。そのため、インターネット上のトランザクション分離レベルに関する記事のほとんどが問題のある内容なので、別の記事を書いて説明します!

この記事の内容のほとんどは公式サイトでサポートされています。そのため、この記事を読んだ後は、概念を頭に覚えておくことができます。公式サイトの開発マニュアルが間違っていない限り、正しいはずです。

さらに、この記事では

Repeatable Read は本当にファントムリードの問題を解決するのでしょうか?

文章

まず、トランザクションの分離レベルに応じて、3 つの状況が発生する可能性があることを述べておきます。つまり、ダーティ リード、反復不可能なリード、ファントム リードです。ここではこれら 3 つの状況の定義については触れませんが、後で分離レベルについて説明するときに追加します。

ここで、ダーティ リード、非反復リード、ファントム リードの定義 (自己要約、公式 Web サイトでは利用できません) によれば、次の包含関係があることを誰もが覚えておく必要があります。


では、この絵をどう理解すればよいのでしょうか?

つまり、ダーティ リードが発生すると、繰り返し不可能なリードとファントム リードが必ず発生します。ダーティ リードの現象は、非反復読み取りとファントム リードの定義によって説明できるためです。しかし一方で、非反復読み取りの現象は、ダーティ リードの定義では説明できない可能性があります。

次のようなテーブルtx_tbがあると仮定します。pIdは主キーです。

pI名前
1張山

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

実際、これは分離という名前からもわかります。あるトランザクションは、別のトランザクションのコミットされていないデータを読み取ることができます。説明のために、簡単に絵を描いて説明します。

図に示すように、1 つのトランザクションによって取得されたデータは、コミットされていない別のトランザクションによって変更されました。

公式サイトでダーティリード用に定義されているアドレスは

https://dev.mysql.com/doc/refman/5.7/en/glossary.html#glos_dirty_read

その内容は

**ダーティリード
信頼性の低いデータ、つまり別のトランザクションによって更新されたがまだコミットされていないデータを取得する操作。
**

翻訳すると

操作から取得されたデータは信頼性が低く、コミットされていない別のトランザクションによって変更される可能性があります。

私たちのデモンストレーションの結果は、公式ウェブサイトのダーティ リードの定義と一致していることがわかります。当初の推論によれば、ダーティ リードが存在する場合、非反復リードとファントム リードも存在するはずです。

2. コミットされた読み取り (READ_COMMITTED)

これは、1 つのトランザクションが別のトランザクションによって送信されたデータを読み取ることができることも示しています。説明のために、簡単に絵を描いて説明します。

図に示すように、1 つのトランザクションによって取得されたデータは、コミットされた別のトランザクションによってのみ変更できます。

公式サイトで非反復読み取り用に定義されているアドレスは

https://dev.mysql.com/doc/refman/5.7/en/glossary.html#glos_non_repeatable_read

その内容は

**繰り返し不可能な読み取り
クエリがデータを取得し、同じトランザクション内の後続のクエリが同じデータを取得するはずであるが、クエリが異なる結果を返す (その間に別のトランザクションがコミットすることによって変更される) 状況。
**

翻訳すると

クエリ ステートメントがデータを取得し、次に別のクエリ ステートメントが同じトランザクションでデータを取得します。2 つのデータは同じであるはずですが、実際には異なる結果が返されます。 !

ps: 著者注: ここでの異なる結果は、行は変更されていない (より専門的に言えば、主キー インデックスは変更されていない) が、主キー インデックスによって指されるディスク上のデータ コンテンツが変更されている状況を示しています。新しいデータの追加やデータの削除など、主キー インデックスが変更された場合、それは反復不可能な読み取りではありません。

明らかに、私たちの現象は非反復読み取りの定義を満たしています。次に、これについて考えてみましょう。

この非反復読み取りの定義は、ダーティ読み取りの現象にも適用できます。明らかに、ダーティ リードの現象、つまり **READ_UNCOMMITTED** の例も、同じトランザクションで異なる結果を返すという条件を満たしています。ただし、逆は必ずしも真ではありません。トランザクション A の 2 つのクエリの結果が別のトランザクション B によって変更され、トランザクション B がコミットされずにトランザクション A の結果を変更する場合、それはダーティ リードであり、反復不可能なリードでもあります。トランザクション A の結果を変更する前にトランザクション B がコミットされた場合、それはダーティ リードではなく、反復不可能なリードになります。 3. 繰り返し読み取り (REPEATABLE_READ)

ここでは順序を変えて、まずファントムリーディングを定義します。

ファントムリーディングの公式サイトで定義されているアドレスは

https://dev.mysql.com/doc/refman/5.7/en/glossary.html#glos_phantom

ファントム
クエリの結果セットに表示されるが、以前のクエリの結果セットには表示されない行。たとえば、トランザクション内でクエリが 2 回実行され、その間に別のトランザクションが新しい行を挿入するか、クエリの WHERE 句と一致するように行を更新した後にコミットした場合などです。

翻訳すると

あるクエリの結果セットにはデータ行が表示されますが、そのデータは以前のクエリの結果セットには表示されません。たとえば、1 つのトランザクションで 2 つのクエリが実行され、同時に別のトランザクションが行を挿入するか、データ行を更新し (データがクエリ ステートメントの where の後の条件を満たす)、コミットします。

さて、下の写真を見てみましょう。この現象がファントムリーディングの定義を満たしているかどうかは、あなた自身で判断してください。

明らかに、この現象はファントムリーディングの定義を満たしています。同じトランザクションからの 2 つの同一クエリによって、異なる行が生成されます。次に、これについて考えてみましょう。

このファントム リード定義は、非反復読み取り現象にも適用できます。自分で考えてみてください!その逆は必ずしも真ではありません。トランザクションは 2 回目にデータの一部をクエリしましたが、そのデータは最初のクエリの結果セットに表示されませんでした。データが変更されたデータの場合、この現象は非反復読み取りとファントム読み取りの両方になります。データが新しく追加または削除された場合、この現象は非反復読み取りではなく、ファントム読み取りに属します。

次に、多くの記事が、繰り返し読み取りによってファントム読み取りの問題を解決できると読者に誤解を与えている理由についてお話ししましょう。その理由は公式サイトの一文から来ている
(アドレス: https://dev.mysql.com/doc/refman/5.7/en/innodb-locking.html#innodb-record-locks)

元のコンテンツは次のとおりです

デフォルトでは、InnoDB は REPEATABLE READ トランザクション分離レベルで動作します。この場合、InnoDB は検索とインデックス スキャンに次のキー ロックを使用し、ファントム行を防止します (セクション 14.7.4「ファントム行」を参照)。

この文の本来の意味によれば、

InnoDB はデフォルトで REPEATABLE READ を使用します。この場合、次のキー ロックを使用してファントム リードの問題を解決してください。

国内の翻訳者がそれを翻訳したと推定される。

InnoDB はデフォルトで REPEATABLE READ を使用します。この場合、ファントムリードの問題を解決できます。

それから皆が私を真似し続け、私もあなたを真似しました。結果はご存知の通りです!

明らかに、「ネクストキーロックが使用される」という条件を省略すると、意味は完全に変わり、この分離レベルでステートメントを実行します。

select * from tx_tb where pId >= 1;

これはスナップショット読み取りであり、ロックを追加せず、ファントム読み取り問題をまったく解決できません。

select * from tx_tb where pId >= 1 lock in share mode;

このように、ネクストキーロックを使用してファントムリード問題を解決します。

4. シリアル読み取り(SERIALIZABLE_READ)

この分離レベルでは、すべての選択ステートメントの後に共有モードでのロックが自動的に実行されます。したがって、この分離レベルでは、クエリの方法に関係なく、次のキー ロックが使用されます。すべての選択操作は現在の読み取りです。


さて、上の表の赤い部分に注目してください。ネクストキーロックの使用により、InnoDB はインデックスレコード PiD=1 とギャップ (1,++∞) をロックします。他のトランザクションがこのギャップにデータを挿入しようとすると、ブロックされ、ファントム読み取りの発生を防ぎます。

2 回目のクエリの結果も変更され、明らかに最初のクエリの結果と異なると言う人もいるかもしれません。この点については、注意深く確認してくださいとしか言​​えません。これは自分自身で

これはトランザクションによって変更されるものであり、他の要因によって変更されるものではありません。これはファントム リードではなく、反復不可能なリードでもありません。

要約する

上記は意味不明な部分が多いので、表にまとめてみました。面接ではこの表に答えてください。上記はすべてこのテーブルの準備です。

分離レベルダーティリード繰り返し不可能な読み取りファントムリード
コミットされていない読み取りはいはいはい
繰り返し不可能な読み取りいいえはいはい
繰り返し読み取りいいえいいえはい
シリアル化いいえいいえいいえ

以上がこの記事の全内容です。皆様の勉強のお役に立てれば幸いです。また、123WORDPRESS.COM を応援していただければ幸いです。

以下もご興味があるかもしれません:
  • MySQL トランザクション分離レベルの詳細
  • MySQL トランザクション分離レベルとロックメカニズムの問題に関する深い理解
  • MySQL シリーズ 10 同時実行制御を実装するための MySQL トランザクション分離
  • Mysql トランザクション分離レベルの読み取りコミットの詳細な説明
  • MySQLトランザクションの4つの分離レベルについての深い理解

<<:  Vue+Websocketはチャット機能を実装するだけです

>>:  Zabbixで監視する必要があるホストを追加するための詳細な手順

推薦する

Alibaba Cloudのセキュリティルール設定の詳細な説明

2日前、ダブル11ショッピングフェスティバルを利用して、Alibaba CloudでECS(サーバー...

CentOS 8.4 に Docker をインストールする詳細なチュートリアル

目次序文:システム要件:インストール環境:古いバージョンをアンインストールします: yum は具体的...

Vue の計算プロパティ

目次1. 基本的な例2. 計算プロパティキャッシュとメソッド3. 計算プロパティセッター序文:通常、...

Node.js で MySQL データベースにバッチデータを挿入する方法

プロジェクト(nodejs)では、一度に複数のデータをデータベースに挿入する必要があります。データベ...

プライベートレジストリ内の画像を照会または取得する方法

Dockerはプライベートレジストリ内のイメージを照会または取得するために、 docker 検索 1...

docker に基づいて nginxssl 設定を開始する

前提条件クラウドサーバー(Alibaba Cloud、Tencent CloudなどのcentOS)...

WeChatアプレットタブの左右スライドスイッチ機能実装コード

効果画像: 1. はじめに独自のアプレットでこのような機能を実装する必要がある1. 核となる考え方ス...

Nginx リバース プロキシと負荷分散の実践

リバースプロキシリバースプロキシとは、プロキシサーバーを介してユーザーのアクセス要求を受信し、ユーザ...

Homebrewを使用してMacにMySQLをインストールするときにログインできない問題を解決する

お使いのコンピュータが Mac の場合、homebrew を使用して MySQL をインストールする...

1行のコードでLinuxのプロセスを隠す方法を学ぶ

友人たちはいつも、Linux のプロセスを隠す方法を私に尋ねます。私は、どの程度隠したいのか、カーネ...

VueはTodoListの例をカプセル化し、ブラウザのローカルキャッシュのアプリケーションを実装します。

この記事では主に、Vue で TodoList をカプセル化するケースと、ブラウザのローカル キャッ...

Vue2.0/3.0双方向データバインディングの実装原理の詳細説明

Vue2.0/3.0双方向データバインディングの実装原理双方向データバインディングとは、データの変更...

Raspberry Pi msmtp と mutt のインストールと設定のチュートリアル

1. muttをインストールするsudo apt-get install mutt 2. msmtp...

メタタグの詳しい説明(メタタグの役割)

個人のウェブサイトがどんなに素晴らしいものであっても、サイバースペースの広大な海に浮かぶ小さなボート...

Dockerでデータディレクトリを移行する方法

目次ディスク使用量の表示ディスク クリーンアップ (軽々しく使用しないでください)データの移行ディス...