MySQLのMVCCマルチバージョン同時実行制御の実装

MySQLのMVCCマルチバージョン同時実行制御の実装

1 MVCCとは何か

MVCC の正式名称は、マルチバージョン同時実行制御です。データベースへの同時アクセスを提供するときにトランザクション内でメモリ読み取りを処理し、書き込み操作が読み取り操作をブロックするという同時実行の問題を回避します。

たとえば、プログラマー A がデータベース内の特定のコンテンツを読み取り、プログラマー B がこのコンテンツを変更しているとします (変更が約 10 秒続くトランザクション内で行われると仮定)。A は、この 10 秒以内に不整合なデータを見る可能性があります。B がコミットする前に、A は常に整合性のあるデータを読み取ることができるのでしょうか。

これに対処するにはいくつかの方法があります。最初の方法は、ロックベースの同時実行制御です。プログラマー B がデータを変更し始めると、データをロックします。この時点でプログラマー A がデータを読み取ると、読み取れず待機状態になっていることがわかります。B が操作を完了した後にのみ、データを読み取ることができます。これにより、A が矛盾したデータを読み取らないことが保証されますが、プログラムの実行効率に影響します。もう 1 つあります。MVCC です。各ユーザーがデータベースに接続すると、特定の瞬間のデータベースのスナップショットが表示されます。B のトランザクションがコミットされる前に、A は常に特定の瞬間のデータベースのスナップショットを読み取り、B のトランザクションでのデータ変更は読み取りません。B のトランザクションがコミットされた場合にのみ、A は B の変更を読み取ることができます。

MVCC をサポートするデータベースは、特定のデータを更新するときに、古いデータを新しいデータで上書きするのではなく、古いデータを古いものとしてマークし、別の場所に新しいデータ バージョンを追加します。したがって、同じデータの複数のバージョンが保存されますが、最新のものは 1 つだけです。

MVCC は、時間の一貫性を実現するソリューションを提供します。MVCC でトランザクションを読み取る場合、通常、タイムスタンプまたはトランザクション ID を使用して、アクセスするデータベースの状態とデータのバージョンを決定します。読み取りトランザクションと書き込みトランザクションは互いに分離されており、相互に影響を与えません。同じデータが読み取りトランザクションと書き込みトランザクションの両方からアクセスされると仮定します。実際には、書き込みトランザクションは新しいデータ バージョンを作成し、読み取りトランザクションは古いデータ バージョンにアクセスします。読み取りトランザクションは、書き込みトランザクションがコミットされるまで、新しいデータ バージョンにアクセスしません。

MVCC を実装する方法は 2 つあります。1 つ目は、データベースに複数のバージョンのデータ レコードを保存する方法です。これらの異なるバージョンのデータが不要になると、ガベージ コレクターがこれらのレコードを回収します。この方法は、PostgreSQL および Firebird/Interbase で採用されています。SQL Server も同様のメカニズムを使用しますが、違いは、古いバージョンのデータがデータベースに保存されるのではなく、メイン データベースとは異なる別のデータベース (tempdb) に保存される点です。 2 番目の実装方法では、データベースに最新バージョンのデータのみを保存しますが、元に戻す操作を行うと、古いバージョンのデータが動的に再構築されます。この方法は、Oracle および MySQL/InnoDB で使用されます。

2. InnoDBのMVCC実装メカニズム

MVCC は行レベル ロックのバリエーションと見なすことができ、多くの場合ロック操作を回避できるため、オーバーヘッドが低くなります。ほとんどの MVCC 実装では非ブロッキング読み取り操作が実装され、書き込み操作では必要な行のみがロックされます。 InnoDB の MVCC 実装は、特定の時点でのデータのスナップショットを保存することによって実現されます。トランザクションの実行にどれだけ時間がかかっても、その中に表示されるデータは一貫しています。つまり、トランザクションは実行中に互いに影響を及ぼしません。以下では、InnoDB での MVCC の実装について簡単に説明します。

InnoDB の MVCC は、各レコード行の後に 2 つの隠し列を保存することで実装されています。1 つの列には行の作成時刻が保存され、もう 1 つの列には行の有効期限 (削除時刻) が保存されます。もちろん、ここでの時刻はタイムスタンプではなく、システム バージョン番号です。新しいトランザクションが開始されるたびに、システム バージョン番号が増加します。 RR 分離レベルでは、MVCC は次のように動作します。

操作を選択します。

InnoDB は、現在のトランザクション バージョンよりも前のバージョン (またはそれと等しいバージョン) のデータ行のみを検索します。トランザクションによって読み取られる行は、トランザクションの開始前に存在しているか、トランザクション自体によって挿入または変更されたレコードであることが保証されます。

削除された行のバージョンは未定義であるか、現在のトランザクション バージョン番号よりも大きいです。トランザクションによって読み取られた行が、トランザクションの開始前に削除されていないことを確認できます。

挿入操作。新しく挿入された行の現在のバージョン番号を行バージョン番号として保存します。

削除操作。削除された行の現在のバージョン番号を削除マークとして保存します。

更新操作。これは、挿入操作と削除操作の組み合わせになります。挿入された行は現在のバージョン番号を行バージョン番号として保存し、削除では現在のバージョン番号が削除マーカーとして元の行に保存されます。

古いデータは実際には削除されていないため、クリーンアップする必要があります。InnoDB は、クリーンアップを実行するためにバックグラウンド スレッドを開始します。具体的なルールは、現在のシステム バージョンよりもバージョン番号が小さい行を削除することです。このプロセスはパージと呼ばれます。

3. 簡単な例

テーブルyang(を作成 
    id int 主キー auto_increment, 
    名前varchar(20));
}

システムのバージョン番号は 1 から始まると仮定します。

入れる

InnoDB は、新しく挿入された各行のバージョン番号として現在のシステム バージョン番号を保存します。
最初のトランザクション ID は 1 です。

トランザクションを開始します。
yang 値に挿入します (NULL、'yang')。
ヤン値(NULL,'long')に挿入します。
yang 値に挿入します (NULL、'fei')。
専念;

データ内の対応するテーブルは次のとおりです (最後の 2 つの列は非表示の列であり、クエリ ステートメントでは表示されません)

選択

InnoDB は各行を次の 2 つの条件と照合します。
a. InnoDB は、現在のトランザクション バージョンよりも前のバージョンのデータ行のみを検索します (つまり、行のシステム バージョン番号がトランザクションのシステム バージョン番号以下です)。これにより、トランザクションによって読み取られる行は、トランザクションの開始前に存在しているか、トランザクション自体によって挿入または変更されていることが保証されます。
b. 削除された行のバージョンは未定義であるか、現在のトランザクション バージョン番号より大きいため、トランザクションによって読み取られた行はトランザクションの開始前に削除されていないことが保証されます。
a と b の両方を満たすレコードのみがクエリ結果として返されます。

消去

InnoDB は、削除された各行の削除識別子として現在のシステム バージョン番号 (トランザクション ID) を保存します。
次の具体的な分析例を参照してください。
2 番目のトランザクション、ID は 2 です。

トランザクションを開始します。
ヤンから*を選択; //(1)
ヤンから*を選択します。 //(2)
専念;

仮定1

トランザクションID 2の実行中に(1)に達したときに、別のトランザクションID 3がテーブルにレコードを挿入すると仮定します。
3 番目のトランザクション ID は 3 です。

トランザクションを開始します。
yang 値に挿入します (NULL、'tian')。
専念;

表のデータは次のとおりです。

次に、トランザクション2の(2)を実行します。id=4のデータの作成時刻(トランザクションIDは3)、現在のトランザクションIDは2であり、InnoDBは現在のトランザクションID以下のトランザクションIDのデータ行のみを検索するため、トランザクション2の(2)ではid=4のデータ行は取得されません。トランザクション2の2つの選択文で取得されるデータは以下のもののみとなります。

仮定2

トランザクションID 2の実行中に、(1)を実行したと仮定します。トランザクションがトランザクション3を実行した後、トランザクション4を実行すると仮定します。
4番目のトランザクション:

トランザクションを開始します。  
id=1 の yang から削除します。
専念;

この時点でデータベース内のテーブルは次のようになります。

次に、トランザクションID 2のトランザクション(2)を実行します。SELECT検索条件に従って、作成時刻(作成トランザクションのID)が現在のトランザクションIDより小さく、削除時刻(削除トランザクションのID)が現在のトランザクションIDより大きい行を検索します。id=4の行は前述のとおりで、id=1の行は削除時刻(削除トランザクションのID)が現在のトランザクションIDより大きいです。そのため、トランザクション2(2)のselect * from yangもid=1のデータを検索します。そのため、トランザクション2の2つのselect文で検索されるデータは以下のようになります。

アップデート
InnoDB が UPDATE を実行すると、実際には新しいレコード行が挿入され、その作成時刻が現在のトランザクションの ID として保存されます。また、現在のトランザクション ID から UPDATE 対象の行への削除時刻も保存されます。

仮定3
トランザクション 2 (1) を実行した後、他のユーザーがトランザクション 3 と 4 を実行するとします。このとき、別のユーザーがこのテーブルに対して UPDATE 操作を実行します。
5番目のタスク:

トランザクションを開始します。
yang を更新し、name='Long' を設定します (id=2)。
専念;

更新の原則に従って、新しい行が生成され、変更される元の列の削除時間列にトランザクション ID が追加され、次のテーブルが作成されます。

トランザクション2の(2)の実行を続けます。SELECT文の検索条件に従って、次のテーブルが得られます。

トランザクション2(1)選択と同じ結果が得られます。

MySQL MVCC マルチバージョン同時実行制御の実装に関するこの記事はこれで終わりです。MySQL MVCC マルチバージョン同時実行制御に関するより関連性の高いコンテンツについては、123WORDPRESS.COM の以前の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • MySQL マルチバージョン同時実行制御 MVCC の実装
  • MySQL マルチバージョン同時実行制御メカニズム (MVCC) ソースコードの詳細な説明
  • MySQL マルチバージョン同時実行制御 MVCC の詳細な研究
  • MySQL マルチバージョン同時実行制御 MVCC の基本原理の分析
  • MySQL マルチバージョン同時実行制御 MVCC の実装
  • Mysql MVCC マルチバージョン同時実行制御の詳細

<<:  ユーザーエクスペリエンスの概要

>>:  JavaScript 関数のカリー化

推薦する

wavesurfer.js によるオーディオ波形描画の実装

1. レンダリングを見る進むを選択: 後方を選択: コードは次のとおりです(例): <テンプレ...

Windows での MySQL 8.0.13 解凍バージョンのインストール グラフィック チュートリアル

この記事では、参考までにMySQL 8.0.13のインストールグラフィックチュートリアルを紹介します...

Centos6.5 でのスーパーバイザーのアップグレード、インストール、および構成に関するチュートリアル

スーパーバイザー紹介Supervisor は、Python で開発されたクライアント/サーバー サー...

TypeScript のマップされた型とより優れたリテラル型推論について説明します。

目次概要マップされた型を使用して Object.freeze() を構築するマッピングタイプの構文は...

Ubuntu 20.04の新バージョンでルートユーザーを使用してシステムにログインする方法の詳細なチュートリアル

Ubuntu 20.04 では、デフォルトで root ログインが有効になっていないため、デスクトッ...

MySQL におけるデータベース間関連クエリメソッド

ビジネスシナリオ: 異なるデータベース内のテーブルをクエリするたとえば、関連付けられるテーブルは、マ...

ウェブページの画像の回転を実現するjs

この記事では、Webページの画像の回転を実現するためのjsの具体的なコードを参考までに共有します。具...

MySQLとOracleのメタデータ抽出例分析

目次序文メタデータとは参照文書アドレスまずはMySQLについてお話しましょうOracleについて話し...

JavaScript はパスワードボックスの入力検証を実装します

サーバーの負荷を軽減するために、ユーザーが入力するときにフロントエンドページで簡単な検証を実行する必...

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

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

Linux システムでの nginx サーバーのインストールと負荷分散構成の詳細な説明

nginx (エンジン x) は、高性能な HTTP およびリバース プロキシ サーバー、メール プ...

HTML ページ適応幅テーブル

WEB アプリケーションのページでは、テーブルがよく使用されます。列の数が限られているため、各列のコ...

XHTML Web ページ チュートリアル

この記事は主に、初心者に XHTML の基本的な知識と、XHTML と HTML の違いを理解しても...

React双方向データバインディングの原理についての簡単な説明

目次双方向データバインディングとは双方向データバインディングの実装データ影響ビュービューはデータに影...

MySQLの累積集計原理と使用例の分析

この記事では、例を使用して、MySQL 累積集計の原理と使用方法を説明します。ご参考までに、詳細は以...