この記事は、mysql ログに関する関連知識を提供します。注目する必要があるのは、バイナリ ログ (binlog) とトランザクション ログ (REDO ログと UNDO ログを含む) です。皆様のお役に立てれば幸いです。
1、binlog
binlog は、データベースによって実行された書き込み操作 (クエリを除く) 情報を記録するために使用され、バイナリ形式で保存されます。ディスク。 binlog は mysql の論理ログであり、サーバー層によって記録されます。任意のストレージ エンジンを使用する Mysql データベースは binlog ログを記録します。
- 論理ログ: 単純に SQL ステートメントとして理解できます;
- 物理ログ: MySQL のデータはデータ ページに保存され、物理ログはデータ ページにデータを記録します。データ ページ。変更します。ここにコード スニペットを挿入します。
バイナリは追加によって書き込まれます。各バイナリ ファイルのサイズは、max_binlog_size パラメータを通じて設定できます。ファイル サイズが指定された値に達すると、ファイル サイズは次のようになります。ログを保存するための新しいファイルが生成されました。
binlog 使用シナリオ
プロジェクト 実際のアプリケーションでは、binlog には 2 つの主な使用シナリオ、つまりマスター/スレーブ レプリケーションとデータ リカバリがあります。
- マスター/スレーブ レプリケーション: マスター側でバイナリ ログを有効にし、バイナリ ログを各スレーブ側に送信します。スレーブ側はバイナリ ログを再生して、マスターとスレーブのデータの一貫性を実現します。
- データリカバリ: mysqlbinlog ツールを使用してデータをリカバリします。
MySQL マスター/スレーブ同期原理
- マスター ノードのバイナリ ダンプ スレッド
ノードの接続 マスター ノードが使用される場合、マスター ノードはログ ダンプ スレッドを作成して、バイナリ ログの内容を送信します。ビンログの操作を読み取るとき、このスレッドはマスター ノードのビンログをロックします。読み取りが完了すると、ロックはスレーブ ノードに送信される前でも解放されます。
- スレーブ ノード I/Oスレッド
スレーブ ノードでスレーブ開始コマンドを実行した後、スレーブ ノードはマスター ノードに接続するための I/O スレッドを作成し、マスター ライブラリ内の更新されたバイナリログを要求します。 I/O スレッドは、マスター ノードのバイナリ ログ ダンプ プロセスから更新を受信した後、それをローカルのリレーログに保存します。
- スレーブ ノード SQL スレッド
SQL スレッドは、リレーログの内容を読み取る責任があります。そしてそれを特定の操作と実行に解析し、最終的にマスターとスレーブのデータの一貫性を確保します。
MySQL データベースのマスターとスレーブの同期原理
binlog content
として上で説明したように、binlog は、論理ログは単純に SQL ステートメントとして理解できますが、実際には、実行された SQL ステートメントの逆のロジックも含まれています。 delete は削除自体と逆挿入情報に対応し、update には対応する更新が実行される前後のデータ行に関する情報が含まれ、insert には独自の挿入情報と対応する削除情報が含まれます。
binlog 形式
binlog 形式には、ステートメント、行、混合の 3 つがあります。 MySQL 5.7.7 より前では、デフォルトでステートメントが使用され、MySQL 5.7.7 以降では、デフォルトで行が使用されていました。ログの形式は、my.ini 構成ファイルの binlog-format を通じて変更できます。
(1) ステートメント: SQL ステートメントに基づくステートメントベースのレプリケーション (SBR) データを変更する各 SQL ステートメントはバイナリログに記録されます。
- 利点: 特定の行の変更を具体的に記録する必要がないため、スペースが節約され、IO が削減され、パフォーマンスが向上します。
- 欠点: sysdate() やスリープなどの操作を実行する場合() 、マスター データとスレーブ データの間で不整合が生じる可能性があります。
(2) 行: 行ベース レプリケーション (RBR)、SQL ステートメントのコンテキスト関連情報は記録されませんが、どの情報が記録されるか変更されるレコードの詳細。
- 利点: 各行レコードの変更の詳細が非常に詳細に記録されるため、データが正しくコピーできない状況は発生しません;
- 欠点: 各行は非常に詳細に記録される 変更の詳細を記録します。これにより、大量のログ コンテンツが生成されます。 update ステートメントがあり、多くのレコードが変更されたとすると、変更された各レコードは binlog に記録されます。特に、テーブルの変更操作では、テーブル構造の変更によりレコードの各行が変更され、その結果、ログの量が急激に増加します;
(3)mixed:上記、ステートメント、および行 それぞれに長所と短所があるため、混合バージョンは 2 つを混合したものであるように見えます。通常はステートメント形式で保存しますが、ステートメントが解けない場合は行形式で保存します。
特に、上で述べたように、新しいバージョン (MySQL 5.7.7 以降) では、デフォルトで行形式が使用されます。ここでの行も、それに応じて最適化されています。テーブル変更操作が発生した場合、記録にはステートメント形式が使用されます。残りの操作では引き続き行形式が使用されます。
binlog フラッシュのタイミング
InnoDB ストレージ エンジンの場合、binlog はトランザクションが送信されたときにのみ記録されます。この時点では、レコードはまだメモリ内にあります。 、MySQL は sync_binlog を渡し、binlog のフラッシュのタイミングを制御します。値の範囲は 0 ~ N:
- 0: ディスクへの強制フラッシュはありません。いつディスクに書き込むかはシステムが決定します;
- 1: 送信ごとにバイナリログをディスクに書き込む必要があります;
- N: Binlog は N トランザクションごとにディスクに書き込まれます;
上記からわかるように、sync_binlog の最も安全な設定は 1 であり、これは MySQL 5.7.7 以降のバージョンのデフォルト値でもあります。ただし、より大きな値を設定するとデータベースのパフォーマンスが向上するため、実際の状況では、値を適切に増やし、ある程度の一貫性を犠牲にしてパフォーマンスを向上させることもできます。
binlog の物理ファイル サイズ
my.ini 構成ファイルでは、binlog のサイズは max_binlog_size を通じて構成できます。ログのボリュームが binlog ファイルのサイズを超えると、システムは新しいファイルを再生成してファイルの保存を続行します。トランザクションが比較的大きい場合、またはログが増えて、トランザクションが占有する物理スペースが大きすぎる場合はどうすればよいでしょうか? MySQL には自動削除メカニズムが用意されており、これは my.ini 設定ファイルのexpire_logs_days パラメータを日単位で設定することで解決できます。このパラメータが 0 の場合は削除されないことを意味し、N の場合は N 日目後に自動的に削除されることを意味します。
2. redo ログ
redolog は、InnoDB エンジンの独自のログ システムです。これは主にトランザクションの耐久性とクラッシュセーフ機能を実現するために使用されます。 Redolog は物理ログであり、SQL ステートメントの実行後にデータ ページ上の特定の変更を記録します。
MySQL の実行中にデータがディスクからメモリにロードされることは誰もが知っています。 SQL文を実行してデータを変更した場合、実際には変更内容は一時的にメモリ上に保存されるだけで、このときに電源が切れるなどの事情が発生すると変更内容は失われます。したがって、データを変更した後、MySQL はこれらのメモリ レコードをディスクにフラッシュする機会を探します。しかし、主に 2 つの側面でパフォーマンスの問題があります:
InnoDB はページのデータ単位でディスクと対話し、完全なデータ ページがフラッシュされた場合、トランザクションはページ上の数バイトのみを変更する可能性があります。ディスクに戻すと、リソースが無駄になります。
トランザクションには、複数のデータ ページが含まれる場合があります。これらのデータ ページは、論理的に連続しているだけで、物理的に連続していません。ランダム IO を使用します。パフォーマンスが低すぎます。
したがって、MySQL は、トランザクションによってデータ ページに加えられた特定の変更を記録し、その REDO ログをディスクにフラッシュするように REDO ログを設計しました。疑問に思われるかもしれませんが、もともと io を減らしたかったのですが、これでは別の io が追加されるのではないか? InnoDB の設計者は、設計の開始時にこれらを考慮しました。通常、REDOLOG ファイルは比較的小さく、ディスクにフラッシュバックするプロセスはシーケンシャル IO であるため、ランダム IO よりもパフォーマンスが優れています。
REDO ログの基本概念
REDOLOG は 2 つの部分で構成されます。1 つはメモリ内のログ キャッシュ REDO ログ バッファで、もう 1 つはメモリ内のログ ファイル REDO ログ ファイルです。ディスク。データ レコードが変更されるたびに、これらの変更はまず REDO ログ バッファに書き込まれ、その後、メモリ内の変更が REDO ログ ファイルにフラッシュされる適切な機会を待ちます。最初にログを書き込んでからディスクに書き込むこの技術が WAL (Write-Ahead Logging) 技術です。 REDO ログはデータ ページの前にディスクにフラッシュされることに注意してください。クラスタード インデックス、セカンダリ インデックス、および UNDO ページへの変更はすべて REDO ログに記録する必要があります。
コンピュータ オペレーティング システムでは、ユーザー空間のバッファ データは通常、ディスクに直接書き込むことができず、オペレーティング システムのカーネル空間バッファ (OS バッファ) を経由する必要があります。)。したがって、REDO ログ バッファを REDO ログ ファイルに書き込むと、実際には最初に OS バッファに書き込まれ、次にシステム コール fsync() を通じて REDO ログ ファイルにフラッシュされます。プロセスは次のとおりです。
mysql サポート innodb_flush_log_at_trx_commit パラメータを使用して、REDO ログ バッファを REDO ログ ファイルに書き込む 3 つのタイミングを設定できます。各パラメータ値の意味は次のとおりです:
パラメータ値
#意味 |
|
0 (遅延書き込み)
トランザクションがコミットされると、REDO ログ バッファー内のログがOS バッファには書き込まれませんが、毎秒 OS バッファに書き込み、fsync() を呼び出して REDO ログ ファイルに書き込みます。つまり、0 に設定すると、データは (約) 毎秒ディスクに書き込まれ、システムがクラッシュすると 1 秒間のデータが失われます。 |
|
1 (リアルタイム書き込み、リアルタイムブラッシング)
トランザクションが送信されるたびに、REDO ログ バッファ内のログが OS に書き込まれます。バッファと fsync() が呼び出され、REDO ログ ファイルにフラッシュされます。この方法では、システムがクラッシュしてもデータは失われませんが、各送信がディスクに書き込まれるため、IO パフォーマンスは低下します。 |
|
2 (リアルタイム書き込み、遅延ブラッシング)
各送信は OS バッファーにのみ書き込まれ、その後 fsync() が毎秒呼び出され、 OS バッファ内のデータ ログは REDO ログ ファイルに書き込まれます。 |
|
redo ログの記録形式
REDO ログは固定サイズ、周期書き込み形式を採用しており、REDO ログがいっぱいになると再度最初から書き込まれます。なぜこのように設計されているのでしょうか?
REDO ログの主な目的は、データ ページのフラッシュの要件を軽減することです。 Redolog はデータ ページの変更を記録しますが、データ ページもディスクにフラッシュバックされると、これらの記録は役に立たなくなります。したがって、MySQL が以前の redolog の有効期限が切れたと判断すると、新しいデータが無効なデータを上書きします。では、対象となるべきかどうかはどのように判断すればよいのでしょうか?
上の図はREDOログファイルの模式図で、write posはREDOLOGが現在記録しているログシーケンス番号LSN(ログシーケンス番号)を表します。データ ページがディスクにフラッシュされると、REDO ログ ファイル内の LSN が更新され、この LSN より前のデータがディスクに書き込まれたことが示されます。この LSN がチェック ポイントです。書き込み pos とチェック ポイントの間の部分は、新しいレコードを記録するために使用される redolog の予備部分です。チェック ポイントと書き込み pos の間の部分は、redolog が記録したデータ ページの変更された部分ですが、データ ページは変更されていません。この時点でディスクにフラッシュバックされました。書き込み pos がチェック ポイントに追いつくと、まずチェック ポイントを前方に押し出し、その位置を空けてから、新しいログを記録します。
innodb を起動すると、前回正常にシャットダウンされたか異常にシャットダウンされたかに関係なく、常に回復操作が実行されます。リカバリ中、最初にデータ ページ内の LSN がチェックされ、この LSN が REDO ログ内の LSN、つまり書き込み位置より小さい場合、データ ページ上の未完了の操作が REDO ログに記録されていることを意味します。そして、最も近いチェックポイントから開始され、データの同期が開始されます。
データ ページの LSN が redolog の LSN より大きい可能性はありますか?答えはもちろん可能です。これが発生すると、redolog 以降の部分はやり直しされません。これ自体、実行された内容をやり直す必要がないことを意味するためです。
REDO ログと binlog の違い
| ##REDO ログ | binlog |
ファイル サイズ | REDO ログのサイズは固定です。 | Binlog は、構成パラメータ max_binlog_size を通じて各 binlog ファイルのサイズを設定できます。 |
実装方法 | REDO ログは InnoDB エンジン層によって実装され、すべてのエンジンがこれを備えているわけではありません。 | Binlog はサーバー層で実装されており、すべてのエンジンで binlog ログを使用できます |
記録方法 | REDO ログはループ書き込み方式で記録されます。最後まで書き込むと最初に戻ってループでログを書き込みます。 | binlog は追加で記録されます。ファイル サイズが指定された値より大きい場合、以降のログは新しいファイルに記録されます |
適用可能なシナリオ | redo ログはクラッシュ リカバリに適しています (クラッシュ セーフ) | binlog はマスター/スレーブ レプリケーションとデータ リカバリに適しています |
これは、binlog と REDO ログの違いからわかります。binlog ログはアーカイブにのみ使用され、binlog のみに依存するとクラッシュ セーフ機能がありません。ただし、REDO ログだけは機能しません。REDO ログは InnoDB に固有であり、ログ内のレコードはディスクに書き込まれた後に上書きされるからです。したがって、データベースをシャットダウンして再起動したときにデータが失われないように、binlog と REDO ログの両方を同時に記録する必要があります。
2 段階の送信
上記では redolog と binlog について簡単に紹介しましたが、データを変更する場合、これらの変更を保存して実装しますが、1 つは物理ログ、もう 1 つは論理ログです。では、彼らはどのようにして修正プロセスを実行したのでしょうか?
今実行する update ステートメントがあるとします。update from table_name set c=c 1 where id=2、実行プロセスは次のとおりです。
- 最初にレコードを見つけます。 with id=2 ;
- エグゼキューターはエンジンによって与えられた行データを取得し、この値に 1 を加えて新しいデータ行を取得し、エンジン インターフェイスを呼び出してこの新しいデータ行を書き込みます。
##エンジンは新しいデータをメモリに更新し、更新操作を redolog に記録します。このとき、redolog は準備状態になります。次に、実行が完了し、いつでもトランザクションを送信できることが実行者に通知されます。- 実行者は、この操作のバイナリログを生成し、そのバイナリログをディスクに書き込みます。
- 実行者は、エンジンのコミット トランザクション インターフェイスを呼び出し、エンジンは書き込まれたばかりの REDO ログをコミット状態に変更し、更新が完了します。
-
#概略図は次のとおりです:
これにより redolog の書き込みが分割されます。準備とコミットのプロセスは 2 フェーズ コミットと呼ばれます。
redolog と binlog はどちらもトランザクションのコミット ステータスを表すために使用できます。2 フェーズ コミットは 2 つの状態の論理的な一貫性を維持するために使用されます。 2 フェーズ コミットを使用せず、一方を最初に記述し、次にもう一方を記述した場合、問題が発生する可能性があります。 現時点では、更新はまだ例として使用されています。現在の id=2 で、フィールド c=0 があると仮定します。次の状況をそれぞれ分析します:
最初に redolog を書き込み、次に binlog を書き込みます redolog が最初に書き込まれると仮定します。完了しましたが、binlog はまだ書き込まれていません。書き終えたとき、MySQL が突然例外に遭遇し、再起動されました。 redolog は以前に書き込まれているため、システムの再起動後も変更されたレコードがまだ存在するため、リカバリ後のこの行の c の値は 1 になります。ただし、システムが再起動されたため、このレコードはバイナリログに存在しません。後でログをバックアップすると、このステートメントは保存されたバイナリログには存在しません。次に、このバイナリ ログを使用して一時ライブラリを復元する必要がある場合、このステートメントのバイナリ ログが失われているため、今回は一時ライブラリは更新されないことがわかります。復元された行の c の値は 0 です。元のライブラリの値と同じですが、異なります。
最初に binlog を書き込み、次に redolog を書き込みます。 最初に binlog を書き込み、次に redolog を書き込むときにシステムを再起動します。再起動後、redolog には c を変更した記録はなく、この時点では c の値は 0 のままです。ただし、binlog には「c を 0 から 1 に変更する」というログが記録されています。そのため、後で binlog を使用して復元すると、トランザクションが 1 つ増えてしまい、復元された行の c の値は 1 となり、元のデータベースの値とは異なります。
したがって、要約すると、最初にログが書き込まれ、次に別のログが書き込まれると、データベースのステータスは、binlog を使用して復元されたライブラリのステータスと一致しなくなります。 3. undo logundolog は主に、特定の行レコードが変更される前の状態を記録するために使用され、変更前のデータを記録します。この場合、トランザクションがロールバックされると、undolog を通じてレコードをトランザクションが開始される前の状態に復元できます。トランザクションの原子性と耐久性も undolog によって実現されます。アンドゥ ログは主にデータの論理的な変更を記録します。たとえば、INSERT ステートメントは DELETE アンドゥ ログに対応します。各 UPDATE ステートメントについては、反対側の UPDATE アンドゥ ログに対応するため、エラーが発生したときにロールアップできます。トランザクション前のデータ状態に戻ります。同時に、データ回復を実行するときに、binlog および redolog と組み合わせて使用され、データ回復の正確性を保証します。 アンドゥログの機能プロセスは次のとおりです:
#トランザクションの開始前に、変更前のバージョンをアンドゥ ログに書き込みます。 - 変更を開始し、変更したデータをメモリに保存します;
- アンドゥログをディスクに保存します;
- データ ページをディスクにフラッシュして戻します;
- トランザクション コミット;
-
redolog と同様に、undolog はデータ ページの前にディスクにフラッシュバックする必要があることに注意してください。データをリカバリするときに、アンドゥログが完了している場合は、アンドゥログに基づいてトランザクションをロールバックできます。
トランザクションでは、同じデータが複数回変更される可能性があるため、各変更前の記録をアンドゥログに記録する必要がありますか?この場合、アンドゥログのログ量が多くなりすぎるため、この時にリドログが活躍することになります。トランザクション内で同じレコードが変更された場合、undolog はトランザクション開始前の元のレコードのみを記録し、このレコードが再度変更されると、redolog はその後の変更を記録します。データのリカバリ中、redolog はロールフォワードを完了し、undolog はロールバックを完了し、この 2 つが相互に連携してデータのリカバリを完了します。
もう 1 つの機能は MVCC マルチバージョン コントロール チェーンです。この記事を参照してください
MySQL の MVCC 実装原理
binlog、redolog、Undologは MySQL の 3 つの最も重要なログであり、データ回復中に、これら 3 つが調整および協力して、データ回復の正確性を保証します。
推奨学習: mysql ビデオ チュートリアル
以上がMySQL の 3 つの主要なログ: binlog、redo ログ、undo ログを完全にマスターするの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。