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 8.0.17 をインストールしてリモート アクセスを構成する方法

1. インストール前の準備データベースのバージョンを確認するコマンド: mysql --versio...

CSS 動的読み込みバー効果のサンプルコード

CSS変数の知識を使って、追加したコードとコメントを直接投稿します <!DOCTYPE htm...

Vue実戦記録のログインページの実装

目次1. 事前準備1.1 Node.jsをインストールする1.2 webpackをインストールする1...

CSS3でハートを描く

成果を達成する要件/機能: CSS + HTML を使用してハートを描く方法。分析:正方形と 2 つ...

CSS ボックスモデル内のパディングと略語の詳細な説明

上図のように、パディング値は時計回り(右上、右下)の複合属性であり、パディングの内側の余白がボックス...

EclipseのプロジェクトをTomcatに追加できない問題を解決する方法

1. プロジェクトを右クリックしてプロパティを選択します2. プロジェクトファセットをクリック3. ...

HTML ファイルにファイルの内容を含める方法の概要

フォーラムでは、ネットユーザーから「HTML ファイル内の別の HTML ファイルの内容を読み取るこ...

MYSQL での Truncate の使用法の詳細な説明

この記事のガイド: テーブル内のデータを削除するには、削除と切り捨ての 2 つの方法があります。TR...

JSはスネークゲームを実装する

目次1. 初期化構造2. 蛇の色のレンダリング3. ヘビの動き4. ヘビの死を判定する方法 ヘビの死...

Vue の動的コンポーネントと非同期コンポーネントの詳細な理解

1. 動的コンポーネント <!DOCTYPE html> <html> &l...

MySQL では SQL ステートメントはどのように実行されますか?

目次1. MySQLアーキテクチャの分析1.1 コネクタ1.2 クエリキャッシュ1.3 アナライザー...

YUMを使用してdockerをインストールする方法

次の図に示すように: Centos 7.0以上であれば問題ありません。現在のシステム カーネル バー...

Dockerの国内イメージソースを変更する方法

Dockerデーモンのアクセラレータを構成する設定ファイルから Docker を起動し、/etc/d...

jQuery は呼吸カルーセルを実装します

この記事では、ブレッシングカルーセルを実装するためのjQueryの具体的なコードを参考までに共有しま...

MySQLの暗黙的な変換について話す

作業の過程で、暗黙的な変換が発生するケースが数多くあります。暗黙的な変換は、クエリの速度低下を引き起...