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 メソッドの紹介

MySQLでテーブルやデータを削除する場合、 [エラー] 1451 - 親行を削除または更新できませ...

フレックスとポジションの互換性の詳細な説明マイニングノート

今日は、すべてのブラウザ (主に IE 9 以上と Chrome) と互換性のある自分のホームページ...

LinuxのCPU負荷とCPU使用率の詳細な説明

CPU 負荷と CPU 使用率これらは両方とも、ある程度、マシンの忙しさを反映できます。 CPU 使...

InnoDB エンジンのパフォーマンスを最適化するための my.cnf パラメータ構成

私はインターネット上で数え切れないほどの my.cnf 構成を読みましたが、言及されている構成のほと...

CSS変数を使用してスタイルを変更する方法の例

質問js を使用して CSS 疑似クラス スタイルを変更するにはどうすればよいでしょうか?しかし、j...

MySQL の効率的なクエリの左結合とグループ化 (プラス インデックス)

mysql 効率的なクエリMySQL は、左結合の速度を上げるために group by を犠牲にし...

Vue はクリックフリップ効果を実現します

参考までに、vueを使用してクリックフリップエフェクトを簡単に実装します。具体的な内容は次のとおりで...

Dockerコンテナに入る方法と出る方法

1 Dockerサービスを開始するまず、docker サービスを開始する方法を知っておく必要がありま...

フックを使用して React コンポーネントを書くときに注意すべき 5 つの点

目次01. レンダリングが不要な場合はuseStateを使用する02. リンクの代わりにrouter...

dockerにros2をインストールするための詳細な手順

目次メイントピック1. UbuntuにDockerをインストールする2. DockerにROS2-F...

MySQL 学習ノート ヘルプ ドキュメント

システムヘルプを表示help contents mysql> ヘルプコンテンツ; ヘルプ カテ...

Docker で Python スクリプトを実行する方法

まず、Docker イメージ用の特定のプロジェクト ディレクトリを作成します。例: mkdir /h...

3次元画像配置効果を実現する純粋なCSSのサンプルコード

1. 要素の幅/高さ/パディング/マージンのパーセンテージ基準要素の幅/高さ/パディング/マージンの...

Windows で MySQL 5.7.17 をインストールし、エンコードを utf8 に設定する方法

ダウンロードMySQL 公式ダウンロード、Windows (x86、64 ビット)、ZIP アーカイ...

iOS WeChat H5ページのゴム反発効果の落とし穴記録

ビジネス要件最近開発したプロジェクトの一つに、WeChat公式アカウントに関連したH5ページがありま...