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 と trx2 には 2 つの異なる値が表示されます。 テーブルには実際には最新の値 (trx1 が参照する値) のみが含まれており、trx2 が参照する値またはレコードは UNDO ログ レコードから取得されます。 よりよく理解するために、下の図を見てみましょう。 初期状態: 更新操作前 次の図は更新操作前の状況を示しています。 元に戻すログは空です。 テーブルのクラスター化インデックスには 1 つの行が含まれます。 テーブルに LOB があります。 クラスター化インデックス レコードには LOB への参照が含まれています。 最終状態: 更新操作後 次に、更新操作後に何が起こるかを見てみましょう。 ここにいくつかの重要な観察事項を示します。
接続 1 のトランザクションによって実行される手順は次のとおりです。
部分的な更新が行われない場合、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 参照と、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 を応援していただきありがとうございます。 以下もご興味があるかもしれません:
|
<<: Dockerfile echoは、指定されたファイル内の複数行のテキストを実装する方法を指定します。
>>: Vue で axios を使用して画像をアップロードするときに発生する問題
Vue でフォーム フィールドを記述および検証する方法は多数あります。このブログでは、より一般的に使...
プログラマーは MySQL を扱う機会が多く、毎日触れているとも言えますが、MySQL テーブルには...
目次サーバー計画1. システムコンポーネントをインストールする2. fastdfsをインストールする...
この記事では、bootstrapテーブルの使い方を参考までに紹介します。具体的な内容は次のとおりです...
1. マスタースレーブレプリケーションとは何ですか?マスタースレーブレプリケーションは、スレーブデー...
1.公式サイトからインストールパッケージをダウンロードするhttp://nginx.org/en/d...
同僚から、LINUX サーバー上の多くのコマンドが (コマンドが見つかりません) というプロンプトで...
序文私はプログラマーとしてスタートした PHP プログラマーです。これまで、トレーニング コースで勉...
1. docker-maven-pluginの紹介私たちの継続的インテグレーションプロセスでは、プロ...
目次1.ソケットを作成する2. ソケットをバインドする3. 聞き手を作る。聞く4. 接続が受け入れら...
コードをコピーコードは次のとおりです。 <!DOCTYPE html PUBLIC "...
<br />ポテトチップスパーティーのこのエピソードに参加して、何人かの友達に会えてとて...
この質問は非常に奇妙なので、あまり多くを語らずにコードに直接進みます。 .g-ダイアログラッパー{ ...
目次概要方法1: params経由でパラメータを渡す方法2: クエリを通じてパラメータを渡す方法3:...