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で監視する必要があるホストを追加するための詳細な手順

推薦する

CSS を使用して ul と li の水平配置を実現する 2 つの方法

li はブロックレベル要素であり、デフォルトで 1 行を占めるため、水平方向の配置を実現する場合は、...

負荷分散の基礎知識とnginxを使用した負荷分散の簡単な例

Nginx は、一般的に 7 層の負荷分散に使用できます。この記事では、負荷分散に関する基本的な知識...

ドラッグ可能で編集可能なガントチャートの詳細な説明(HighchartsはVueとReactで使用できます)

序文Excel は強力で、広く使用されています。 Web アプリケーションの登場と改善に伴い、ユーザ...

Vueカウンターの実装

目次1. カウンターの実装2. 成果を達成する1. カウンターの実装ページにカウンターを実装するだけ...

mysql8.0.23 msi インストールの超詳細なチュートリアル

1.MySqlをダウンロードしてインストールする公式ウェブサイトからMySqlデータベースをダウンロ...

レスポンシブWebデザイン学習(1) - 画面サイズと使用率の決定

最近では、モバイルデバイスがますます普及しており、ユーザーがスマートフォンやタブレットを使用して W...

HTML テキストエスケープのヒント

今日、CSDN で HTML テキスト エスケープのちょっとしたトリックを見ましたが、とても簡単です...

MySQL Installer Community 5.7.16 インストール詳細チュートリアル

この記事では、MySQL インストールの詳細なチュートリアルを記録し、全員と共有します。 1. バー...

CocosCreator で http と WebSocket を使用する方法

目次1. HTTPGET 2. HTTP POSTウェブソケット4. Egretのhttpとwebs...

MySQLデータベースのbinlogクリーンアップコマンドの詳細な説明

概要今日は主に、MySQL データベースから binlog ログを正しく削除する方法を紹介します。ロ...

MySql 共通クエリコマンド操作リスト

MYSQL でよく使用されるクエリ コマンド: mysql> select version()...

ソースコードから MySQL 8.0.20 をコンパイルしてインストールする詳細なチュートリアル

前回の記事では、次のことを紹介しました。 MySQL8.0.20 インストール チュートリアルとイン...

Nexus サーバーを設定するための詳細な手順

1. ネクサスサービス構築の意義イントラネットの統合プロキシとして、チームで共同開発する場合、全員が...

デザイン理論: デザインにおける階層

<br />原文: http://andymao.com/andy/post/80.ht...

ドロップダウンリストのJavaScript実装

この記事の例では、ドロップダウンリストを実装するためのJavaScriptの具体的なコードを参考まで...