MySQL 8.0 redo ログの詳細な分析

MySQL 8.0 redo ログの詳細な分析

序文

MySQL の実装について初めて学んだとき、REDO ログ、WAL (先行書き込みログ)、UNDO ログなどのキーワードを常に耳にしていました。REDO ログは主にトランザクションの永続性を実現するために使用されていることを知りました。 redo ログをさらに理解するために、関連するコード (ソース コード バージョン: MySQL 8.0.12) を確認しました。ここでは、redo ログがどのように生成されるか、どのようにディスクに書き込まれるか、そして最終的にユーザーに通知される方法を中心に、簡単にまとめます。

REDOログの生成

読み取り/書き込みトランザクションの実行中、REDO ログが継続的に生成されます。データ ページの適用、データ ページの変更、UNDO ログの記録などを行うと、REDO ログが生成されます。 MySQL は、ユーザー トランザクションを mtr (ミニ トランザクション) に分割します。REDO ログは、最初に生成されると mtr に記録され、mtr の送信とともにコミットされ、最終的にハード ディスクに保存されます。

REDOログ送信

mtr が送信されると、mtr 内の redo ログがシステム変数 log_sys のログ バッファーに書き込まれます。 MySQL 8.0 の新機能は、ロックフリーの REDO ログ送信です。 8.0 より前では、各ユーザー スレッドがミューテックスを競合し、ログ バッファーにシリアルに書き込んでいたため、LSN がギャップなく順番に増加していました。 8.0 では、ユーザー スレッドは同時にログ バッファーに書き込むことができます。ユーザー スレッドがログ バッファーに正常に書き込み、その後ディスクに書き込んだ LSN の前にログ バッファーをフラッシュすると、他のユーザー スレッドが書き込みを完了する前にログ バッファーをフラッシュする可能性があります。

この問題を解決するために、MySQL 8.0 ではログ バッファ ホールを回避する Link_buf データ構造が導入されました。 Link_buf は、実際には固定長の配列であり、スライディング ウィンドウのようにログ バッファーのセクションの書き込みステータスを追跡し、連続した REDO ログがログ バッファーに書き込まれるにつれて前進します。

Link_buf のデータ構造は次のとおりです。

ユーザーがログ バッファーの start_lsn と end_lsn の間に REDO ログを書き込むと、Link_buf の対応する位置がマークされます。つまり、m_link[start_lsn%m_capacity] に end_lsn-start_lsn の値が割り当てられます。

ログ バッファへの REDO ログ記録のプロセスは次のとおりです。

1. まず、各ユーザー スレッドが redo ログを書き込むときに、redo ログの長さに応じて、システム グローバル アトミック変数 log_sys.sn から redo ログの start_lsn と end_lsn を取得します。アトミック変数 sn は、各スレッドによって取得される start_lsn-end_lsn 間隔が穴なく連続していることを保証できます。

2. ユーザー スレッドが start_lsn-end_lsn 間隔を適用した後、Link_buf が使用可能な位置まで進むまで待機する必要があります。

図に示すように、start_lsn0-end_lsn0、start_lsn2-end_lsn2、start_lsn3-end_lsn3 は、3 つのユーザー スレッドに新しく適用された LSN 間隔です。start_lsn1-end_lsn1 に対応する間隔は link_buf にマークされています。start_lsn3-end_lsn3 は末尾から離れすぎているため、link_buf が進むまで待機してから使用する必要があります。

3. ログ バッファーに書き込んだ後、start_lsn->end_lsn の範囲を link_buf にマークします (注: link_buf は start_lsn%capacity の位置にのみマークされるため、end_lsn が (m_tail、m_tail+m_capacity) を超えても影響を受けません)。

4. ユーザー スレッドがトランザクションをコミットすると、イベント log_sys.writer_event が設定され、log_writer スレッドがログを redo ログ バッファーからシステム キャッシュに書き込むようにトリガーされます (log_writer スレッド自体も link_buf をポーリングして、新しいログが書き込まれたかどうかを判断します)。

5. log_writer スレッドは m_tail を進め、m_tail の前のログ バッファーをディスクに書き込みます。

REDOログの保存と通知

前のセクションでは、REDO ログがどのように送信されるかについて簡単に説明しました。REDO ログが送信され、ディスクに書き込まれるときには、複数のスレッドが関与します。それらの関係は次のとおりです。

ユーザー スレッドが読み取り/書き込みトランザクションをコミットすると、mtr がコミットされるときにいくつかの redo ログが生成され、redo ログ バッファーに記録されます。次に、ユーザー スレッドは writer_event を設定して log_writer スレッドによるログの書き込みをトリガーし、独自の flush_events[i] イベントをリッスンしようとします。

log_writer スレッドは Link_buf.m_tail を進め、最大連続 LSN の前の redo ログをシステム キャッシュに書き込み、log_flusher スレッドをトリガーする flusher_event を設定します。

log_flusher スレッドは、システム キャッシュに書き込まれたログをディスクにフラッシュし、flush_notifier_event を設定して log_flush_notifier スレッドをトリガーし、ユーザーに通知します。

log_flush_notifier は、フラッシュされたディスクの LSN に基づいてトリガーする必要があるイベントを計算し、ユーザー スレッドに通知します。

具体的な実装では、log_sys 内のいくつかのメンバー変数を使用して、REDO ログの書き込みステータスを追跡します。 log_sys.recent_writtern.m_tail はログ バッファーの最大連続範囲を示します。log_sys.write_lsn はデータがシステム キャッシュに書き込まれる場所を示します。log_sys.flushed_to_disk_lsn はデータがディスクにフラッシュされた場所を示します。各マークの昇格プロセスは次のとおりです。

ユーザースレッドに通知

ユーザーがトランザクションをコミットすると、innodb_flush_log_at_trx_commit パラメータに従って log_wait_for_write または log_wait_for_flush が呼び出され、REDO ログがシステム キャッシュに書き込まれるか、ハード ディスクにフラッシュされるまで待機します。ユーザー スレッドの通知は、log_sys.flush_events イベント配列を通じて実装されます。一度に通知される flush_events が多すぎるのを避けるために、flush_events はバケットのように異なるユーザー スレッドに分割されます。REDO ログはログ ブロックに分割されます。log_sys.flush_events 配列の長さが m であると仮定すると、n 番目のログ ブロックのフラッシュは flush_events[n%m] イベントによって監視されます。ログ バッファーの L1 番目のログ ブロックから L2 番目のログ ブロックまでがディスクにフラッシュされると、L1 と L2 の間のログ ブロックの flush_events が設定され、L1 と L2 の間の redo ログのユーザー スレッドが通知を受け取ります。

要約する

MySQL 8.0 では、REDO ログをロックフリーにすることで、ユーザー スレッドが REDO ログを書き込むときにロック競合によって発生するパフォーマンスへの影響を解決します。同時に、REDO ログのファイル書き込みと REDO ログのフラッシュはユーザー スレッドから分離され、別のスレッドに抽出されます。ユーザー スレッドは、REDO ログをログ バッファに書き込むことだけを担当し、ディスクへの REDO ログのフラッシュの詳細については気にする必要がなくなります。log_writer スレッドまたは log_flusher スレッドからの通知を待つだけで済みます。

上記は、MySQL 8.0 redo ログの徹底的な分析の詳細な内容です。MySQL 8.0 redo ログの詳細については、123WORDPRESS.COM の他の関連記事に注目してください。

以下もご興味があるかもしれません:
  • MySQL の redo ログと binlog の違いを 1 つの記事で理解する
  • MySQL における redo ログと binlog の違い
  • MySQL の undo、redo、binlog の違いを簡単に分析します
  • Redo ログと Undo ログに基づく MySQL クラッシュ回復の分析
  • MySQLのREDOログとUNDOログの詳細な説明
  • MySQL Undo ログと Redo ログの概要
  • MySQL シリーズ: redo ログ、undo ログ、binlog の詳細な説明
  • MySQLのREDOログ(リドゥログ)とロールバックログ(アンドゥログ)の詳しい説明
  • MySQL redo logの詳細な理解 redo log

<<:  CSSアニメーション属性キーフレームの詳細な説明

>>:  複数の Docker コンテナが同じポート番号を持たない場合の解決策

推薦する

mysql 5.7.11 winx64.zip インストールと設定方法のグラフィックチュートリアル

MySql データベース システムをインストールして構成します。 1. ダウンロード http://...

MySQL の悲観的ロックと楽観的ロックの理解と応用分析

この記事では、例を使用して MySQL の悲観的ロックと楽観的ロックについて説明します。ご参考までに...

JavaScript Promise の徹底解説

目次1. Promise とは何ですか? 2. なぜ Promise が存在するのでしょうか? 3つ...

ハードコーディングに別れを告げ、フロントエンドテーブルがインスタンスコードを自動的に計算できるようにします。

序文私のチームが税制モジュールを開発していたとき、計算問題、特にグリッド内の計算を解決するために時間...

LinuxシステムにおけるMySQLの一般的な操作コマンド

仕える: # chkconfig --list すべてのシステムサービスを一覧表示する# chkco...

Linux でパスワードを入力せずに sudo コマンドを実行する方法

sudo コマンドを使用すると、信頼できるユーザーは別のユーザー (デフォルトでは root ユーザ...

MySQL 8.0.24 リリースノートのいくつかの改善点

目次1. 接続管理2. オプティマイザレベルでの改善3. 機能の改善4. パフォーマンススキーマの最...

JS がビデオ弾幕効果を実現

これを実現するには、ES6 モジュール開発とオブザーバー モードを使用します。オブザーバー パターン...

初心者のためのWebサイト構築入門 ③ エイリアス(CNAME)レコードとURL転送

①. エイリアス(CNAME)レコードの使用方法:前回の投稿のドメイン名解決では、A レコードの解...

CSS の 4 つのインポート方法と優先順位の簡単な分析

第一に: CSSを導入する4つの方法CSS を導入する方法には、インライン スタイル、埋め込みスタイ...

Nginx コンパイル済み nginx - 新しいモジュールを追加

1. 既存のモジュールを表示する nginx の sbin ディレクトリに nginx の sbin...

LinuxにPHP7をインストールする方法の詳細な説明

Linux に PHP7 をインストールするにはどうすればいいですか? 1. 依存パッケージをインス...

Vue プロジェクトにおけるトランジション コンポーネントの適用の概要

​Vue のトランジションは、アニメーション トランジションをカプセル化するコンポーネントです。一般...

MySQL の複合インデックスはどのように機能しますか?

目次背景複合インデックスを理解する左端一致原則フィールド順序の影響複合インデックスは単一のインデック...

メモリの原則に関する詳細な説明: JS では変数はヒープに保存されるのか、スタックに保存されるのか?

目次1. 冷蔵庫に入りきらない象2. シャドウクローン文字列3. 実際に見た「奇妙なボール」 4. ...