MySQL の 4 つのトランザクション分離レベルを例を使って分析する

MySQL の 4 つのトランザクション分離レベルを例を使って分析する

序文

データベース操作では、同時データ読み取りの正確性を効果的に保証するために、トランザクション分離レベルが提案されています。データベーストランザクションには 4 つの分離レベルがあります。以下では詳細には触れません。詳細な紹介を見てみましょう。

データベース トランザクションには 4 つの分離レベルがあります。

  • コミットされていない読み取り: ダーティ リードが許可されます。つまり、他のセッションのコミットされていないトランザクションによって変更されたデータが読み取られる可能性があります。
  • コミット済み読み取り: コミットされたデータのみを読み取ることができます。このレベルは、Oracle などのほとんどのデータベースのデフォルトです。
  • 繰り返し読み取り: 繰り返し読み取り。同じトランザクション内のすべてのクエリは、トランザクションの開始時に一貫しています。これは、InnoDB のデフォルト レベルです。 SQL 標準では、この分離レベルにより非反復読み取りが排除されますが、ファントム読み取りは依然として存在します。
  • シリアル化可能: 完全にシリアル化された読み取り。各読み取りにはテーブル レベルの共有ロックを取得する必要があり、読み取りと書き込みの両方が相互にブロックされます。

トランザクション分離の概念を初めて知る人は、上記の教科書的な定義に戸惑うかもしれません。以下では、具体的な例を通して 4 つの分離レベルについて説明します。

まず、ユーザー テーブルを作成します。

テーブルユーザーの作成 (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `name` varchar(255) NOT NULL,
 主キー (`id`)、
 一意の `uniq_name` USING BTREE (name)
) ENGINE=`InnoDB` AUTO_INCREMENT=10 デフォルト文字セット utf8 COLLATE utf8_general_ci;

コミットされていない読み取り分離レベル

まず、トランザクション分離レベルをコミット済みの読み取りに設定します。

mysql> セッショントランザクション分離レベルをコミットされていない読み取りに設定します。
クエリは正常、影響を受けた行は 0 行 (0.00 秒)
mysql> @@session.tx_isolation を選択します。
+------------------------+
| @@session.tx_isolation |
+------------------------+
| 読み取り未コミット |
+------------------------+
セット内の 1 行 (0.00 秒)

以下では、2 つのターミナルを開いて、それぞれトランザクション 1 とトランザクション 2 をシミュレートします。ps: 操作 1 と操作 2 は、時系列順に実行されることを意味します。

取引 1

mysql> トランザクションの開始; # 操作 1
クエリは正常、影響を受けた行は 0 行 (0.00 秒)
mysql> insert into user(name) values('ziwenxie'); # 操作 3
クエリは正常、1 行が影響を受けました (0.05 秒)

取引2

mysql> トランザクションを開始; # 操作 2
クエリは正常、影響を受けた行は 0 行 (0.00 秒)
mysql> select * from user; # 操作4
+----+----------+
| ID | 名前 |
+----+----------+
| 10 | ziwenxie |
+----+----------+
セット内の 1 行 (0.00 秒)

上記の実行結果から、コミットされていない読み取りレベルでは、トランザクション 2 でコミットされていないデータがトランザクション 1 で読み取られる可能性があることが明確にわかります。これはダーティ リードです。

コミット読み取り分離レベル

上記のダーティ リード問題は、分離レベルをコミットに設定することで解決できます。

mysql> セッショントランザクション分離レベルを読み取りコミット済みに設定します。

取引 1

mysql> start transaction; # 操作 1 クエリ OK、影響を受けた行数 0 (0.00 秒)
mysql> select * from user; # 操作 3+----+----------+
| ID | 名前 |
+----+----------+
| 10 | ziwenxie |
+----+----------+
セット内の 1 行 (0.00 秒)
mysql> select * from user; # 操作 5. 操作 4 の変更はトランザクション 1 には影響しません+----+----------+
| ID | 名前 |
+----+----------+
| 10 | ziwenxie |
+----+----------+
セット内の 1 行 (0.00 秒)
mysql> select * from user; # 操作 7+----+------+
| ID | 名前 |
+----+------+
| 10 | リシ |
+----+------+
セット内の 1 行 (0.00 秒)
mysql> commit; # 操作 8 クエリ OK、影響を受けた行数 0 (0.00 秒)

取引2

mysql> start transaction; # 操作 2 クエリ OK、影響を受けた行数 0 (0.00 秒)
mysql> update user set name='lisi' where id=10; # 操作 4 クエリ OK、1 行が影響を受けました (0.06 秒)
一致した行: 1 変更された行: 1 警告: 0
mysql> commit; # 操作 6 クエリ OK、影響を受けた行数 0 (0.08 秒)

ダーティ リード問題は解決されましたが、トランザクション 1 の操作 7 では、トランザクション 2 の操作 6 がコミットされた後、同じトランザクションでトランザクション 1 によって 2 回読み取られたデータが異なることに注意してください。これが非反復読み取り問題です。3 番目のトランザクション分離レベルである反復読み取りを使用すると、この問題を解決できます。

繰り返し読み取り分離レベル

MySQL の Innodb ストレージ エンジンのデフォルトのトランザクション分離レベルは繰り返し読み取り分離レベルであるため、追加の設定を行う必要はありません。

取引 1

mysql> start tansactoin; # 操作 1mysql> select * from user; # 操作 5+----+----------+
| ID | 名前 |
+----+----------+
| 10 | ziwenxie |
+----+----------+
セット内の 1 行 (0.00 秒)
mysql> commit; # 操作 6 クエリ OK、影響を受けた行数 0 (0.00 秒)
mysql> select * from user; # 操作 7+----+------+
| ID | 名前 |
+----+------+
| 10 | リシ |
+----+------+
セット内の 1 行 (0.00 秒)

取引2

mysql> start tansactoin; # 操作 2mysql> update user set name='lisi' where id=10; # 操作 3クエリ OK、1 行が影響を受けました (0.00 秒)
一致した行: 1 変更された行: 1 警告: 0
mysql> commit; # 操作4

トランザクション 1 の操作 5 では、操作 3 のトランザクション 2 の更新を読み取りませんでした。コミット後に更新されたデータのみを読み取ることができます。

Innodb はファントム リードを解決しますか?

実は、RR レベルでファントム リードが発生することがあります。InnoDB エンジンは、この問題は MVCC マルチバージョン同時実行制御を使用することで解決されると公式に主張しています。InnoDB が本当にファントム リードを解決するのか検証してみましょう。

表示の便宜上、上記のユーザー テーブルを変更しました。

mysql> テーブルユーザーを変更し、給与を追加します int(11);
クエリは正常、影響を受けた行は 0 行 (0.51 秒)
レコード: 0 重複: 0 警告: 0
mysql> ユーザーから削除します。
クエリは正常、1 行が影響を受けました (0.07 秒)
mysql> ユーザー(名前、給与)に値('ziwenxie'、88888888);を挿入します。
クエリは正常、1 行が影響を受けました (0.07 秒)
mysql> ユーザーから * を選択します。
+----+----------+----------+
| ID | 名前 | 給与 |
+----+----------+----------+
| 10 | ziwenxie | 88888888 |
+----+----------+----------+
セット内の 1 行 (0.00 秒)

取引 1

mysql> start transaction; # 操作 1 クエリ OK、影響を受けた行数 0 (0.00 秒)
mysql> update user set salary='4444'; # 操作 6 は実際には 2 つの行に影響を与えました。ファントム リードは解決されませんでしたか?
クエリは正常、2 行が影響を受けました (0.00 秒)
一致した行: 2 変更された行: 2 警告: 0
mysql> select * from user; # 操作 7、Innodb はファントムリードを完全には解決しません +----+----------+--------+
| ID | 名前 | 給与 |
+----+----------+--------+
| 10 | ziwenxie | 4444 |
| 11 | 張三 | 4444 |
+----+----------+--------+
セット内の 2 行 (0.00 秒)
mysql> commit; # 操作 8 クエリ OK、影響を受けた行数 0 (0.04 秒)

取引2

mysql> start transaction; # 操作 2 クエリ OK、影響を受けた行数 0 (0.00 秒)
mysql> insert into user(name, salary) value('zhangsan', '666666'); # 操作 4 クエリ OK、1 行が影響を受けました (0.00 秒)
mysql> commit; # 操作 5 クエリ OK、影響を受けた行数 0 (0.04 秒)

上記の例から、Innodb は公式に主張されているようにファントム リードを解決しないことがわかりますが、上記のシナリオはあまり一般的ではなく、あまり心配する必要はありません。

シリアル化可能な分離レベル

すべてのトランザクションは最高の分離レベルでシリアルに実行され、ファントム リードは発生しません。パフォーマンスは非常に低下するため、実際の開発ではほとんど使用されません。

要約する

上記はこの記事の全内容です。この記事の内容が皆さんの勉強や仕事に少しでもお役に立てれば幸いです。ご質問があれば、メッセージを残してコミュニケーションしてください。123WORDPRESS.COM をご愛顧いただき、ありがとうございます。

以下もご興味があるかもしれません:
  • MySQLの4つの分離レベルについての深い理解
  • MySQL の 4 つのトランザクション分離レベルの詳細な説明
  • MySQL 分離レベル操作プロセスの詳細説明 (cmd)
  • MySQL トランザクション分離レベルの原則例分析
  • MySQLにおけるトランザクション分離レベルの実装原理の詳細な説明
  • MySQL 分離レベルの詳細な説明と例

<<:  Alibaba Cloud で静的ウェブサイトを素早く構築する方法

>>:  eject を使用せずに create-react-app の設定を変更する方法

推薦する

vue3.0 sfcのセットアップの変更について簡単に説明します。

目次序文標準的なSFCの書き方スクリプト設定可変露出部品の取り付け小道具カスタムイベント要約する序文...

mysql5.7.19 winx64 解凍版のインストールと設定のチュートリアル

mysql 5.7.19 winx64解凍版のインストールチュートリアルを収録しました。具体的な内容...

MySQL 8.0.14 のインストールと設定方法のグラフィックチュートリアル

この記事では、MySQL 8.0.14のインストールと設定のプロセスを記録しています。具体的な内容は...

XHTMLはHTMLのいくつかの廃止された要素を使用しなくなりました

CSS ウェブページレイアウトを行う場合、XHTML1.0 仕様に準拠する必要があることは誰もが知っ...

フォームファイル選択ボックスのスタイルをカスタマイズする例

コードをコピーコードは次のとおりです。 <!DOCTYPE html> <html...

Ubuntu仮想マシンでシリアル通信にcutecomを使用する方法

Ubuntu仮想マシンでのシリアル通信にcutecomを使用する1. cutecomをインストールす...

Vue の element-ui コンポーネントのデフォルトの CSS スタイルを変更する 4 つの方法

目次序文1. グローバル統合オーバーライドを使用する2. .vueファイルを変更する3. コンポーネ...

Vue ライフサイクルの紹介とフック関数の詳細な説明

目次Vueライフサイクルの紹介とフック機能VUEライフサイクルフックVue ライフサイクルの紹介作成...

高品質なコードを書く Web フロントエンド開発実践書の抜粋

(P4) Web 標準は一連の標準で構成されています。中心となる概念は、Web ページの構造、スタイ...

MySQL の左結合操作における on 条件と where 条件の違いの紹介

優先度両方のケースで同じ条件を設定すると、異なる結果セットが生成される可能性があるのは、優先順位のた...

MySqlはページクエリ機能を実装します

まず、ページ分割クエリを使用する理由を明確にする必要があります。データが膨大なため、すべてのデータを...

MySQLは挿入を使用して複数のレコードを挿入し、データを一括で追加します。

table1 に 5 つのレコードを挿入する場合、次のコードは誤りです。 テーブル1に(id,na...

SQL GROUP BYの詳細な説明と簡単な例

GROUP BY ステートメントは、Aggregate 関数と組み合わせて使用​​され、1 つ以上の...

MySQL学習データベース操作DML初心者向け詳細解説

目次1. ステートメントを挿入する1.1 行を挿入する1.2 複数行を挿入する1.3 クエリステート...

HTML でカスタム画像を使用してチェックボックスを表示する方法

チェックボックスの使用を実装するために画像を使用する必要がある場合は、それを使用して実装できます。実...