序文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 の他の関連記事に注目してください。 以下もご興味があるかもしれません:
|
>>: 複数の Docker コンテナが同じポート番号を持たない場合の解決策
1. インストール前の準備データベースのバージョンを確認するコマンド: mysql --versio...
CSS変数の知識を使って、追加したコードとコメントを直接投稿します <!DOCTYPE htm...
目次1. 事前準備1.1 Node.jsをインストールする1.2 webpackをインストールする1...
成果を達成する要件/機能: CSS + HTML を使用してハートを描く方法。分析:正方形と 2 つ...
上図のように、パディング値は時計回り(右上、右下)の複合属性であり、パディングの内側の余白がボックス...
1. プロジェクトを右クリックしてプロパティを選択します2. プロジェクトファセットをクリック3. ...
フォーラムでは、ネットユーザーから「HTML ファイル内の別の HTML ファイルの内容を読み取るこ...
この記事のガイド: テーブル内のデータを削除するには、削除と切り捨ての 2 つの方法があります。TR...
目次1. 初期化構造2. 蛇の色のレンダリング3. ヘビの動き4. ヘビの死を判定する方法 ヘビの死...
1. 動的コンポーネント <!DOCTYPE html> <html> &l...
目次1. MySQLアーキテクチャの分析1.1 コネクタ1.2 クエリキャッシュ1.3 アナライザー...
次の図に示すように: Centos 7.0以上であれば問題ありません。現在のシステム カーネル バー...
Dockerデーモンのアクセラレータを構成する設定ファイルから Docker を起動し、/etc/d...
この記事では、ブレッシングカルーセルを実装するためのjQueryの具体的なコードを参考までに共有しま...
作業の過程で、暗黙的な変換が発生するケースが数多くあります。暗黙的な変換は、クエリの速度低下を引き起...