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 コンテナが同じポート番号を持たない場合の解決策

推薦する

startup.bat をダブルクリックすると Tomcat がクラッシュする問題の解決方法の詳細な説明

Tomcat を学習したばかりのプログラマーにとって、これはよくある間違いです。 1. 環境変数の問...

Linux で Sudo を使用して権限を委譲する

sudo 権限委譲の概要su スイッチ ID: su –l ユーザー名 –c 'コマンド&#...

VUE+Canvasはデスクトップピンボールブロック破壊ゲームのサンプルコードを実装します

誰もがピンボールやレンガ崩しのゲームをプレイしたことがあるでしょう。左と右のキーを使用して、下にある...

MySQL の最適化: InnoDB の最適化

勉強の計画は簡単に中断され、継続するのが困難です。先日、社内で事業の方向性を調整するための会議があり...

2008 年の Web デザインにおける 10 の経験

<br />インターネットは絶えず変化しており、BusinessWeek.com は専門...

JSはクリックドロップ効果を実装します

jsはクリックとドロップの特殊効果を実現します。まずは効果画像を見てみましょうさっそく始めましょう。...

Linux mysql-5.6 でルート パスワードをリセットする方法

1. MySQL サービスが起動しているかどうかを確認します。起動している場合は、MySQL サービ...

Linux での UDP について学ぶ

目次1. UDPとLinuxの基礎の紹介2. 各機能の使い方1. ソケット機能の使用2. バインド機...

マークアップ言語 - 簡略化されたタグ

123WORDPRESS.COM HTML チュートリアル セクションに戻るには、ここをクリックして...

MySQLはOracleシーケンスに似たソリューションを実装しています

MySQLはOracleのようなシーケンスを実装しているOracle は通常、主キー フィールドを処...

Flexレイアウトを使用してヘッドの固定コンテンツ領域のスクロールを実現する方法

ページ ヘッダーの固定レイアウトは、以前は position:fixed を使用して実装されていまし...

Vue ソング プログレス バーのサンプル コード

なお、これはvue-cliで作成したプロジェクトではありません。vue.jsを参照して記述したHTM...

MySQLが大量のデータを処理する際にクエリ速度を最適化するいくつかの方法

実際に参加したプロジェクトでは、MySQL テーブルのデータ量が数百万に達すると、通常の SQL ク...