MySQL トランザクションと分離レベルの基本原理の簡単な分析

MySQL トランザクションと分離レベルの基本原理の簡単な分析

序文

まず、トランザクションとは何かを確認しましょう。トランザクションは、データベース操作の最小の作業単位です。これは、単一の論理作業単位として実行される一連の操作です。これらの操作はシステム全体に送信され、すべて実行されるか、実行されないかのいずれかになります。トランザクションは、分割できない操作のセット (論理作業単位) です。

取引の特徴:

原子性: 原子性とは、トランザクションに含まれるすべての操作が完全に成功するか、完全に失敗してロールバックされることを意味します。一貫性: トランザクション実行の結果、データベースは 1 つの一貫性のある状態から別の一貫性のある状態に変更される必要があります。分離: トランザクションの実行は他のトランザクションによって妨害されることはありません。つまり、トランザクション内で使用される操作とデータは他の同時トランザクションから分離されており、同時に実行されるトランザクションは互いに干渉できません。耐久性: トランザクションがコミットされると、データベース内のデータに加えられた変更は永続的になります。その後の他の操作や障害は、実行結果に影響を与えないはずです。

1. 取引の基本原則の簡単な分析

原子性:

実装原則: 元に戻すログ

UNDO ログはロールバック ログとも呼ばれ、トランザクションの原子性と分離性を実現するための基礎となります。トランザクションがデータベースを変更すると、InnoDB は対応する UNDO ログを生成します。トランザクションが失敗するか、ロールバックが呼び出されてトランザクションがロールバックされた場合、UNDO ログの情報を使用してデータを変更前の状態にロールバックできます。

UNDO ログは、SQL 実行に関連する情報を記録する論理ログです。ロールバックが発生すると、InnoDB は、UNDO ログの内容に従って、前の作業の逆の処理を実行します。つまり、挿入ごとに、ロールバック時に削除が実行され、削除ごとに、ロールバック時に挿入が実行され、更新ごとに、ロールバック時に逆の更新が実行され、データが元に戻ります。

元に戻す操作は、データベース内の「元に戻すセグメント」と呼ばれる特別なセグメントに保存されます。 UNDO セグメントは共有表領域にあります。 Undo は論理ログなので、データベース ロジックを元の状態に復元するだけです。 UNDO ログは REDO ログを生成します。つまり、UNDO ログの生成には REDO ログの生成も伴います。これは、UNDO ログにも永続的な保護が必要であるためです。

UNDO ログ実行記録は、各データが書き込まれる前または変更される前のものです。

ここに画像の説明を挿入

UNDO ログの使用原則: データベース テーブル内の各データ行には、DATA_TRX_ID と DATA_ROLL_PTR の 2 つの列が追加されます (デフォルトの主キーがない場合に自動的に追加される DB_ROW_ID 列もある場合があります)。 DATA_TRX_IDは現在のデータのトランザクションバージョンを示し、DATA_ROLL_PTRはコピーされたばかりのトランザクションバージョンを指します。

UNDO ログ チェーン内の古いバージョン レコード。UNDO ログはリンク リストです。複数のトランザクションがファイルを複数回変更すると、UNDO ログが引き続き生成され、DATA_ROLL_PTR を通じてポイント関係が確立されます。これを図で説明してみましょう。

ここに画像の説明を挿入

このように、トランザクションがロールバックされると、MySQL は UNDO ログの助けを借りてデータを復元し、コミットされていないトランザクションのアトミック性を確保できます。

持続性

実装原則: redo ログ

InnoDB は MySQL のストレージ エンジンであるため、データはディスクに保存されます。ディスク IO を削減し、読み取りパフォーマンスを向上させるために、InnoDB はキャッシュ プール (バッファー プール) を提供します。バッファ プールには、ディスク内のいくつかのデータ ページのマッピングが含まれており、データベースにアクセスするためのバッファとして機能します。データベースからデータを読み取るときは、まずバッファ プールからデータが読み取られます。データがバッファ プールにない場合は、ディスクから読み取られてからバッファ プールに格納されます。データベースにデータを書き込むときは、まずバッファ プールにデータが書き込まれます。バッファ プール内の変更されたデータは、定期的にディスクに更新されます (このプロセスはフラッシュと呼ばれます)。

しかし、これによって新たな問題も発生します。MySQL がクラッシュし、バッファ プール内の変更されたデータがディスクに更新されていない場合、データは失われ、トランザクションの永続性が保証されなくなります。

この問題を解決するために、REDO ログ (REDO ログとも呼ばれる) が導入されました。データが変更されると、バッファ プール内のデータが変更されるだけでなく、その操作は REDO ログにも記録されます。トランザクションがコミットされると、fsync インターフェイスが呼び出され、REDO ログがディスクにフラッシュされます。 MySQL がクラッシュした場合は、再起動時に REDO ログ内のデータを読み取ってデータベースを復元できます。 REDO ログは WAL (Write-ahead ログ) を使用します。すべての変更は送信される前にログに書き込まれるため、MySQL のダウンタイムによってデータが失われることがなく、永続性の要件を満たすことができます。 REDO ログは物理ページ用であり、同時に実行されます。最後のコミットによって、コミットされていないデータが上書きされます。ローカルREDOログ:

ここに画像の説明を挿入

REDO ログにもバッファ (REDO ログ バッファ) があります。トランザクションがコミットされると、すべての変更情報がディスクに更新されます。ユーザーは、変数innodb_flush_log_at_trx_commitの値(デフォルトは1)を制御することで、リフレッシュポリシーを変更することもできます。たとえば、値が2に設定されている場合、リフレッシュは1秒ごとに実行されるように制御され、トランザクションは

トランザクションは高速化されますが、ログが失われるリスクがあります。

SQL 文が実行された後に、REDO ログが記録されます。

ここに画像の説明を挿入

REDO ログも保存する必要があり、ディスク IO が関係するのに、なぜまだそれを使用するのでしょうか?

(1)REDOログの保存はシーケンシャルですが、キャッシュ同期はランダムな操作です。

(2)キャッシュ同期はデータページ単位で行われ、毎回送信されるデータのサイズはREDOログよりも大きくなります。

REDO ログは、データを回復し、コミットされたトランザクションの永続性を確保するために使用されます。

分離:

原理:
(1)書き込み操作が書き込み操作に与える影響:ロック機構により分離が確保される
(2)書き込み操作が読み取り操作に与える影響:MVCCは分離を保証する

一貫性:

一貫性はかなり特殊です。前述の原子性、永続性、分離性はすべて一貫性に役立ちます。さらに、一貫性は、SQL 構文の検証、列タイプの挿入データ型の検証など、データベース自体が提供する保証、およびアプリケーション層が提供する保証にも依存します。たとえば、送金操作の場合、開発者は送金者の残高を差し引き、受取人の残高を増やす必要があります。アプリケーション レベルで問題が発生すると、一貫性は保証されません。

2. 分離レベルの基本原理の分析

トランザクションの基本原則の分析では、分離の原則については詳しく説明されていないため、ここで簡単に紹介します。

まず最初に、マルチバージョン同時実行制御と呼ばれるMySQLのMVCC (MultiVersion Concurrency Control)について紹介します。これは、UNDO ログ読み取りビューに依存して実装されます。元に戻すログについては上で紹介したので、ここでは繰り返しません。読み取りビューは、私たちが通常理解しているデータベース ビューとは異なります。現在のデータ バージョンの可視性を判断するために使用されます。

ReadView には 4 つの主なプロパティがあります。

(1) m_idsは、ReadViewが生成された時点でアクティブなすべてのトランザクションIDを表します。アクティブとは、トランザクションが開始されたがまだコミットされていないことを意味します。

(2)min_trx_idは現在アクティブなmIdの中で最小のトランザクションIDを示します。

(3)max_trx_idはReadViewを生成する際の最大トランザクションIDを示しますが、必ずしもmIds内の最大トランザクションIDとは限りません。

(4).creator_trx_idはReadViewを作成したトランザクションIDを示します。

ここに画像の説明を挿入

注: トランザクションが開かれるたびに、トランザクション ID が 1 つ増加します。トランザクション ID は、グローバル自動増分変数と見なすことができます。最初に開かれたトランザクションは、長い接続などの後続のトランザクションの前にコミットされない可能性があるため、max_trx_id が mIds の最大値であると想定しないでください。

読み取りビューは、上記の 4 つの属性を使用して、トランザクションが読み取るデータのバージョンをどのように決定しますか?

アクセスされたバージョンの data_trx_id が m_ids の最小値より小さい場合、そのバージョンを生成したトランザクションは ReadView が生成される前にコミットされており、そのバージョンは現在のトランザクションからアクセスできることを意味します。

アクセスされたバージョンの data_trx_id 属性値が ReadView の Creator_trx_id 値と同じである場合、現在のトランザクションが変更したレコードにアクセスしているため、現在のトランザクションからそのバージョンにアクセスできることを意味します。

アクセスされたバージョンの data_trx_id 属性値が ReadView の max_trx_id 値より大きい場合、このバージョンを生成したトランザクションは現在のトランザクションが ReadView を生成した後に開かれたため、現在のトランザクションからこのバージョンにアクセスできないことを示します。

アクセスされたバージョンの data_trx_id 属性値が ReadView の min_trx_id と max_trx_id の間にある場合、trx_id 属性値が m_ids リストにあるかどうかを判断する必要があります。ある場合、ReadView の作成時にバージョンを生成したトランザクションがまだアクティブであり、バージョンにアクセスできないことを意味します。ない場合は、ReadView の作成時にバージョンを生成したトランザクションがコミットされており、バージョンにアクセスできることを意味します。

トランザクションがデータ行を読み込む場合、まず上記のルールを使用して、データの最新バージョン、つまりレコード行を判別します。アクセス可能であることが判明した場合は、直接読み取られます。アクセス不可能であることが判明した場合は、DATA_ROLL_PTR ポインターを介して UNDO ログを検索し、読み取れるバージョンが読み込まれるまで各バージョンを再帰的に検索します。読み取れない場合は、空を返します。

したがって、データにアクセスすると、データベースにビューが作成され、ビューの論理結果がアクセスの基準として使用されます。

READ UNCOMMITED (非コミット読み取り): この分離レベルでは、レコードの最新の値が直接返され、ビューの概念はありません。読み取りではロックが追加されないため、書き込み操作によって読み取りプロセス中にデータが変更され、ダーティ リードが発生します。利点は、同時処理パフォーマンスが向上し、並列読み取りと書き込みを実現できることです。

READ COMMITED : この分離レベルでは、このビューは各 SQL ステートメントの実行の開始時に作成されます。 InnoDB は READ COMMITTED で排他ロックを使用し、読み取り時にデータをロックする代わりに MVCC メカニズムを使用します。つまり、読み取りと書き込みの分離メカニズムを採用しています。

REPEATABLE READ : この分離レベルでは、トランザクションの開始時にビューが作成され、トランザクション全体で使用されます。

SERIALIZABLE : この分離レベルでは、並列アクセスを防ぐためにロックを直接使用します。

この時点で、MySQL は MVCC の助けを借りて、繰り返し読み取り分離レベルでファントム読み取りを実際に防止できることがわかったかもしれません。

結論

アトミック性: UNDO ログ (ロールバック ログ) を使用してロールバックを実装し、コミットされていないトランザクションのアトミック性を保証します。

永続性: REDO ログを使用してデータ回復を実現し、コミットされたトランザクションの永続性を保証します。

分離: ロックと MVCC の考え方を使用して、読み取りと書き込みの分離、読み取りと読み取りの並列処理、読み取りと書き込みの並列処理を実現します。

一貫性: 同時実行環境でのロールバック、リカバリ、分離を通じて一貫性を実現します。

これで、MySQL トランザクションと分離レベルの基本原理に関するこの記事は終了です。MySQL トランザクションと分離レベルの詳細については、123WORDPRESS.COM の以前の記事を検索するか、次の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • MySQL トランザクションの詳細
  • MySQL データベースのインデックスとトランザクション
  • MySQL トランザクション分析
  • MySQLデータベースのトランザクションとインデックスの詳細な説明
  • MySQL トランザクション分離はどのように実現されますか?
  • MySQLトランザクションの詳細な分析

<<:  Linux での JDK のインストール (OpenJDK のアンインストールを含む) の概要

>>:  CSSは5つの一般的な2D変換を実装します

ブログ    

推薦する

MySQL パーティションテーブルの制限と制約の詳細な説明

ビルドを無効にするパーティション式では、次の構成はサポートされません。ストアドプロシージャ、ストアド...

小さなプログラムが天井に張り付いてしまう問題を完璧に解決するためにposition:stickyを使用する方法

最近、あるプロジェクトのクライアントが、上部に 2 つのタブ メニューを配置することを要求しました。...

Lua モジュールを使用して WAF を実装する Nginx の原理の分析

目次1. WAFの背景2. WAFとは3. 動作原理4. WAF機能5. WAFと従来のファイアウォ...

MySQL コピーテーブルと許可分析の 3 つの実装方法

テーブルを素早くコピーする方法まず、テーブル db1.t を作成し、1000 行のデータを挿入します...

HTML ベースタグ target=_parent の使用の紹介

<base> タグは、ページ上のすべてのリンクのデフォルトのアドレスまたはデフォルトのタ...

CentOS8でルートパスワードを素早く変更する方法

Centos8仮想マシンを起動し、上下キーを押して図1のインターフェースの最初の行を選択します。図1...

XHTML 入門チュートリアル: XHTML ハイパーリンク

ハイパーリンクはインターネット全体を接続していると言っても過言ではありません。ハイパーリンクは、別の...

LinuxのCentos7でmysql5.7.29を構築する詳細なプロセス

1. MySQLをダウンロードする1.1 ダウンロードアドレスhttps://downloads.m...

js で下線とキャメルケースの変換を実装する (複数の方法)

目次適用シナリオ:方法 1: 正規表現 (推奨)方法2: 配列のreduceメソッドを使用する方法3...

MySQLカーソルの詳細な紹介

目次1. カーソルとは何ですか? 2. カーソルの使い方1. カーソルを宣言する2.カーソルを開く3...

MySQL でのテーブルの作成と削除の詳細な例

テーブル作成コマンドには以下が必要です。 テーブルの名前フィールド名各フィールドを定義します(タイ...

Docker メモリ監視とストレステストの方法

起動していたDockerコンテナはメモリを使い果たした状態になっており、再起動せずにコンテナのメモリ...

jsは、州、市、地区の3レベルのリンクの非選択ドロップダウンボックスバージョンを実現します。

インターネットで3レベルリンクを検索したところ、すべてオプションで書かれていました。突然、別の方法で...

Dockerはプライベートライブラリイメージを完全に削除します

まず、インターネット上の一般的な慣行を見てみましょうデフォルトでは、プライベート ライブラリはイメー...

Dockerにおけるコンテナとイメージの違いについてお話ししましょう

鏡とは何ですか?イメージは、複数のイメージ レイヤー (UnionFS および AUFS ファイル ...