MySQL における大規模オブジェクトのマルチバージョン同時実行制御の詳細な説明

MySQL における大規模オブジェクトのマルチバージョン同時実行制御の詳細な説明

MySQL 8.0: InnoDB のラージ オブジェクトに対する MVCC

この記事では、MySQL InnoDB ストレージ エンジンのラージ オブジェクト (LOB) 向けのマルチバージョン同時実行制御 (MVCC) 設計について説明します。 MySQL 8.0 には、JSON ドキュメントなどの大きなオブジェクトを部分的に更新できる新しい機能があります。 この部分更新機能により、LOB が部分的に更新されたときに LOB に対して MVCC が動作する方法が変更されました。 通常の更新(完全更新)の場合、MVCC は以前のバージョンと同じように動作します。 部分更新が行われない場合の MVCC の動作を確認し、次に LOB の部分更新の使用例を検討します。

MVCC 全般の最新情報

部分的な更新ではない更新を指すために、定期的な更新という用語を使用します。 MVCC を使用して大きなオブジェクトを定期的に更新する方法を例を挙げて説明します。 この目的のために、次のmtr(1)テストケースを使用します。

 テーブル t1 を作成します ( f1 int 主キー、 f2 longblob ) engine = innodb ; 
 t1に値(1、繰り返し('a'、65536))を挿入します。 
 
 トランザクションを開始します。 
 t1を更新し、f2 = repeat ( 'b' , 65536 ) を設定します。ここで、f1 = 1 です。 
 
 -- echo # 接続 con1: 
 -- MySQL クライアントを使用するユーザーの場合は、別のターミナル ウィンドウを開いて新しいリンクを確立する必要がある場合があります (以下も同様)。
 接続 ( con1 、 localhost 、 root 、 、 ) ; 
 -- echo # 古い値 'aaaaaaaaa' を確認する必要があります 
 t1からf1、right (f2、10)を選択し、f1で並べ替えます。 
 
 -- echo # 接続デフォルト: 
 接続のデフォルト; 
 con1を切断します。 
 専念 ; 
 
 テーブル t1 を削除します。

以下の説明を理解するには、上記のテストケースを注意深く理解することが非常に重要です。

テストシナリオは次のとおりです。

最初、テーブル t1 には 1 つのレコード (R1) が含まれています。
トランザクション trx1 はレコードを新しい値に更新します。
trx1 がまだアクティブな間に、別のトランザクション trx2 がレコードを読み取っています。 古い値が読み取られます。

テーブル t1 にはレコードが 1 つだけ (R1) 含まれています。 しかし、trx1 と trx2 には 2 つの異なる値が表示されます。 テーブルには実際には最新の値 (trx1 が参照する値) のみが含まれており、trx2 が参照する値またはレコードは UNDO ログ レコードから取得されます。 よりよく理解するために、下の図を見てみましょう。

初期状態: 更新操作前

次の図は更新操作前の状況を示しています。 元に戻すログは空です。 テーブルのクラスター化インデックスには 1 つの行が含まれます。 テーブルに LOB があります。 クラスター化インデックス レコードには LOB への参照が含まれています。

最終状態: 更新操作後

次に、更新操作後に何が起こるかを見てみましょう。

ここにいくつかの重要な観察事項を示します。

ユーザー表領域には、古い LOB と新しい LOB の 2 つの LOB があります。 古い LOB には、UNDO ログを通じてのみアクセスできます。 クラスター化インデックス レコードは新しい LOB を指します。
更新操作により、更新ベクトルを含む UNDO ログ レコードが作成されました。 この UNDO ログ レコードは古い LOB を指します。
クラスター化インデックス レコードは、DB_ROLL_PTR システム列を通じて UNDO ログ レコードを指します。 このロール ポインターは、クラスター化インデックス レコードの以前のバージョンを構築するために使用できる UNDO ログ レコードを指します。
UNDO レコードには LOB 自体は含まれません。 代わりに、ユーザー表領域に格納されている LOB への参照のみが含まれます。
UNDO ログ レコードに格納される LOB 参照は、クラスター化インデックス レコードに格納される LOB 参照とは異なります。

接続 1 のトランザクションによって実行される手順は次のとおりです。

トランザクションは R1 を調べ、クラスター化インデックス レコードを変更したトランザクションがコミットされていないことを判断します。 これは、そのレコードを読み取ることができないことを意味します (デフォルトの分離レベルは REPEATABLE READ であるため)。
R1 の DB_ROLL_PTR を調べて、UNDO ログ レコードを見つけます。 元に戻すログを使用して、R1 の以前のバージョンをビルドします。
このビルドでは古い R1 を読み取ります。 このバージョンはクラスター化インデックス レコードでは使用できないことに注意してください。 ただし、これは元に戻すレコードを使用してオンザフライで構築されます。
R1 は新しい LOB を指しますが、構築された R1 の古いバージョンは古い LOB を指します。 したがって、結果には古い LOB が含まれます。

部分的な更新が行われない場合、LOB の MVCC はこのように動作します。

MVCC 部分更新

部分更新の場合に MVCC がどのように機能するかを理解するために、別の例を見てみましょう。 JSON ドキュメントの部分的な更新は現在、関数 json_set() と json_replace() を通じてのみサポートされているため、別の例が必要になります。

 テーブル t2 を作成します ( f1 int 主キー、 j json ) engine = InnoDB ; 
 @elem_a を concat ( '"' 、 repeat ( 'a' 、 200 ) 、 '"' ) に設定します。 
 @ elem_a_with_coma を concat ( @ elem_a , ',' ) に設定します。 
 @json_doc を concat ( "[" 、 repeat ( @elem_a_with_coma 、 300 ) 、 @elem_a 、 "]" ) に設定します。 
 
 t2(f1,j)に値(1,@json_doc)を挿入します。 
 
 トランザクションを開始します。 
 t2を更新します。set j = json_set ( j , '$[200]' , repeat ( 'b' , 200 ) )、ここでf1 = 1です。 
 
 -- echo # 接続 con1: 
 接続 ( con1 、 localhost 、 root 、 、 ) ; 
 -- echo # 古い値 'aaaaaaaaa...' を確認する必要があります 
 t2からjson_extract(j,'$[200]')を選択します。 
 
 -- echo # 接続デフォルト: 
 接続のデフォルト; 
 con1を切断します。 
 専念 ;

シナリオは前の例と同じです。 longblob フィールドのみが JSON ドキュメントに変更されました。 ロードされるデータも JSON 形式に準拠するために若干異なります。

ヒント:上記の mtr テスト ケース (両方) にステートメント set debug = '+d, innodb_lob_print' を追加すると、LOB インデックスがサーバー ログ ファイルに出力されます。 LOB インデックスは挿入後すぐに印刷されます。 LOB インデックスにより、保存されている LOB オブジェクトの構造が提供されます。
部分更新操作の前

完全更新操作または部分更新操作前の初期条件は同じであり、上記に示されています。 ただし、下の図には追加情報がいくつか示されています。

グラフに表示されている他の情報を見てみましょう。

クラスター化インデックス レコードに格納されている LOB 参照に、LOB バージョン番号 v1 が含まれるようになりました。 最初の挿入操作中は 1 に設定され、部分更新ごとに増加します。
各 LOB データ ページには、LOB インデックス内にエントリがあります。 各エントリには LOB バージョン情報が含まれています。 LOB データ ページが変更されるたびに、新しいデータを含む新しい LOB データ ページにコピーされ、LOB バージョン番号が増加した新しい LOB インデックス エントリが作成されます。

追加情報は LOB バージョン番号です。 これは、クラスター化インデックス レコード内の LOB 参照と、LOB インデックスの各エントリで使用できます。

部分更新操作後

次の図は、部分更新操作後の状況を示しています。

ここで最も重要な最適化は、ユーザー表領域に LOB が 1 つだけ残っていることです。 変更する必要がある LOB データ ページのみを更新します。 部分更新操作後のこの単一の LOB には、LOB の古いバージョンと新しいバージョンの両方が含まれます。 これは、図の LOB データ ページの v1 および v2 ラベルによって示されています。

もう 1 つの重要な点は、UNDO ログとクラスター化インデックス レコード内の LOB 参照が同じ LOB を指していることです。 しかし、LOB 参照には異なるバージョン番号が含まれています。 UNDO ログ レコード内の LOB 参照には v1 (古いバージョン番号) が含まれ、クラスター化インデックス レコード内の LOB 参照には新しいバージョン番号 v2 が含まれます。

LOB バージョン番号の目的

上記のように、異なるバージョン番号を持つ異なる LOB 参照は同じ LOB を指します。 1 つの LOB には、異なるバージョンのパーツが含まれます。 LOB バージョン番号は、さまざまな LOB 参照が指す正しいバージョンを取得するために使用されます。 このセクションでは、これがどのように行われるかを見ていきます。

LOB インデックスには、LOB を構成する LOB ページのリストが含まれています。 これには、LOB データ ページのページ番号、各 LOB データ ページに含まれるデータの量、およびバージョン番号が含まれます。 このリストの各ノードは LOB インデックス エントリと呼ばれます。 各 LOB インデックス エントリには、古いバージョンのリストが含まれています。 上記の部分更新テストケースの構造を示す図を見てみましょう。

最初は、部分更新が実行される前は、LOB インデックスには合計 4 つのエントリが含まれています。 4 つのエントリのページ番号は 5、6、7、8 です。LOB インデックス エントリには古いバージョンはありません。 4 つのエントリのバージョン番号はすべて 1 です。

いくつかの更新が完了した後、ページ 9 がページ 7 に置き換わり、ページ 7 がページ 9 の古いバージョンとみなされていることに気付きました。ページ番号 9 にはバージョン番号 2 があり、ページ番号 7 にはバージョン番号 1 があります。

部分的な更新が完了した後、バージョン番号 1 の LOB 参照を通じて LOB にアクセスすると、ページ 5 の最初のインデックス エントリが調べられます。 バージョン番号は 1 です。インデックス エントリのバージョン番号が LOB 参照のバージョン番号以下の場合、そのエントリが読み取られます。 したがって、5ページ目が読み上げられます。 すると、6 ページのインデックス エントリが表示されます。 バージョン番号は 1 なので、それが読み取られます。 すると、ページ番号 9 のインデックス エントリが表示されます。 バージョン番号は 2 です。ただし、LOB 参照のバージョン番号は 1 です。インデックス エントリのバージョン番号が LOB 参照のバージョン番号より大きい場合、エントリは読み取られません。 ページ番号 9 のエントリはバージョン 2 なので、古いバージョンが表示されます。 ページ番号 7 の索引エントリがチェックされます。 バージョン番号は 1 なので、それが読み取られます。 この後、ページ番号 8 の索引エントリがチェックされます。 バージョン番号は 1 なので、これも読み込まれます。 これは、レガシー LOB にアクセスする方法です。

部分的な更新が完了した後、バージョン番号 2 の LOB 参照を通じて LOB にアクセスすると、ページ 5 の最初のインデックス エントリが調べられます。 バージョン番号は 1 です。インデックス エントリのバージョン番号が LOB 参照のバージョン番号以下の場合、そのエントリが読み取られます。 したがって、ページ番号 5、6、9、8 が順番に読み取られます。 バージョン番号は常に <= 2 なので、ページ番号 7 にアクセスするために古いバージョンを使用する必要はありません。

覚えておくべきことの 1 つは、LOB は InnoDB 内で独立して存在しないということです。 これはクラスター化インデックス レコードの拡張と見なされます。 LOB がトランザクションに対して可視かどうかは、LOB モジュールによって処理されません。 LOB モジュールはクラスター化インデックス レコードのみを処理します。 トランザクションが LOB にアクセスする場合、それは、クラスター化インデックス レコード内の DB_TRX_ID を使用して、LOB (LOB の特定のバージョンではない) を参照できることを決定したことを意味します。 したがって、LOB モジュールではその側面については心配する必要はありません。 私たちは、特定の LOB バージョン番号に対して正しいコンテンツを提供することにのみ重点を置いています。

結論は

この記事では、InnoDB で大きなオブジェクトに対して MVCC がどのように実行されるかを見てきました。 LOB が部分的に更新されると、複数の LOB 参照が同じ LOB を指す可能性があります。 ただし、バージョン番号は異なります。 これらの LOB バージョン番号を使用すると、正しい LOB コンテンツにアクセスできます。

この情報がお役に立てば幸いです。

MySQLをご利用いただきありがとうございます。

注:

(1)MtrはMini-transactionの略で、文字通り小さなものを意味します。論理的なものと比較して、物理的なものと呼びます。 Innodb ストレージ エンジンの基盤となるモジュールに属します。主に情報のロックとログ記録に使用されます。

要約する

上記はこの記事の全内容です。この記事の内容が皆さんの勉強や仕事に一定の参考学習価値を持つことを願っています。ご質問があれば、メッセージを残してコミュニケーションしてください。123WORDPRESS.COM を応援していただきありがとうございます。

以下もご興味があるかもしれません:
  • MySQL マルチバージョン同時実行制御メカニズム (MVCC) ソースコードの詳細な説明
  • MySQLのMVCCマルチバージョン同時実行制御の実装
  • MySQL 同時実行制御の原則に関する知識ポイント
  • MySQL マルチバージョン同時実行制御 MVCC の実装
  • MySQL の 4 つのトランザクション分離レベルの詳細な説明
  • MySQL の 4 つのトランザクション分離レベルの詳細な説明と比較
  • MySQL トランザクション分離とパフォーマンスへの影響の詳細な分析
  • Innodb トランザクション分離レベルと MySQL のロックの関係に関するチュートリアル
  • MySQL データベースのトランザクション分離レベル (トランザクション分離レベル) の概要
  • MySQL シリーズ 10 同時実行制御を実装するための MySQL トランザクション分離

<<:  Dockerfile echoは、指定されたファイル内の複数行のテキストを実装する方法を指定します。

>>:  Vue で axios を使用して画像をアップロードするときに発生する問題

推薦する

Nginx リバース プロキシ springboot jar パッケージ プロセス分析

Springboot プロジェクトをサーバーにデプロイする方法としては、war パッケージにパッケー...

VMware15 仮想マシン ブリッジ モードでインターネットにアクセスできない問題の解決方法

説明 ソリューションVMware 15 仮想マシン ブリッジ モードではインターネットにアクセスでき...

MongoDBのパフォーマンスを向上させる方法

MongoDB は高性能なデータベースですが、使用していくうちにパフォーマンスの問題が発生することが...

CSS3 における構造擬似クラスセレクターと擬似要素セレクターの使い方の詳細な説明

構造擬似クラスセレクタの紹介構造擬似クラスセレクターは、いくつかの特殊効果を処理するために使用されま...

Dockerfile に基づいて Tomcat イメージを構築する方法

Dockerfile は Docker イメージを構築するために使用されるファイルです。コマンドパラ...

XHTML ブロックレベルタグの概要

* 住所 - 住所* blockquote - ブロック引用* center - 中央揃えブロック*...

1 つの記事で JSON (JavaScript Object Notation) を理解する

目次JSONが登場JSON構造JSONオブジェクトJson オブジェクトと JavaScript オ...

jsは徐々に増加するデジタルアニメーションを実現します

目次背景コンテナを固定し、数字を上にスクロールすることで、スクロールホイールと同様の効果を実現します...

Elementはスクリプトを使用して新しいコンポーネントを自動的に構築します

目次背景element-ui の自動構築はどのように機能しますか?メイクファイル新しい.jsファイル...

MySQL ストアド プロシージャで月ごとにテーブルを作成する方法

詳細には立ち入らずに、コードに直接進みましょう。一緒にコミュニケーションを取り、学びましょう。月ごと...

Taobao ストアでズームインする効果は、スライドショーを使用する原理に似ています。

今日は、スライドを使用する原理に似た、Taobao のフロントエンドのマウス ズーム効果に慣れました...

Vueが初めて要素を取得できなかったときの解決記録

序文Vue で要素を初回取得できない問題の解決方法は、ポップアップ ウィンドウで要素を取得するために...

MySQL での utf8mb4 照合の例

MySQL における一般的な utf8mb4 ソート規則は次のとおりです。 utf8mb4_0900...

Hadoop を使用せずに Linux 環境に Spark のスタンドアロン バージョンをインストールする方法

ビッグデータはますます注目を集めており、ビッグデータのいくつかの構成要素に精通していないと、自慢でき...

CentOS7におけるKVM仮想化の基本管理の詳しい説明

1. kvm仮想化をインストールする : : : : : : : : : : : : : : : :...