この記事では、MySQL の一般的なログの問題について説明します。必要な方は参考にしていただければ幸いです。
MySQL には、REDO ログ (REDO ログ) とアーカイブ ログ (binlog) という 2 つのログがあります。 (推奨コース: MySQL チュートリアル )
このうち、binlog はスタンバイ データベースに使用したり、データベースの履歴データを復元するために保存したりすることができます。これはサーバー層で実装され、すべてのエンジンで共有できます。 REDO ログは InnoDB に固有のログであり、クラッシュ セーフ機能をサポートするために使用されます。
MySQL トランザクションの 2 フェーズ送信について聞いたことがあると思います。これは、トランザクションが送信されるときに、準備とコミットの 2 つの段階に分割されることを意味します。
図 1 は、トランザクションの実行プロセスを示しています。最後の 3 つのステップでは、最初に REDO ログの準備が完了し、次に binlog が書き込まれ、最後に REDO ログのコミット段階に入っていることがわかります。
図 1 2 段階の送信図
ここで、最初に誤解を説明したいと思います。この図は更新の実行ではありませんか?ステートメントはどのようにして呼び出されるのですか?
通常、この質問が生じる理由は、「コミット」 の 2 つの概念を混同しているためです。 commit ステートメント」は、MySQL 構文でトランザクションをコミットするために使用されるコマンドを指します。通常、begin/start トランザクションと組み合わせて使用されます。
この図で使用されている「コミット ステップ」は、トランザクション送信プロセスの小さなステップを指し、最後のステップでもあります。このステップが完了すると、トランザクションが送信されます。
「コミットステートメント」が実行されると、「コミットステップ」が含まれます。
この例では、トランザクションは明示的に開始されていないため、更新ステートメント自体がトランザクションの実行後に送信されるときに使用されます。
次に、
2 フェーズの送信中にさまざまな時点で MySQL が異常に再起動した場合に何が起こるかを分析してみましょう。
図の時間 A でクラッシュが発生した場合、つまり準備ステージで REDO ログが書き込まれた後、バイナリ ログが書き込まれる前にクラッシュが発生した場合、バイナリ ログはまだ書き込まれていません。 . の場合、REDO ログはまだコミットされていないため、クラッシュが復元されるとトランザクションはロールバックされます。この時点では、バイナリログはまだ書き込まれていないため、スタンバイデータベースには転送されません。この時点では、誰もが理解できます。
問題は主に時間 B で発生すること、つまり、バイナリログが書き込まれた後、REDO ログがコミットされる前にクラッシュが発生することを理解していますが、MySQL はクラッシュ リカバリをどのように処理するのでしょうか?
まずはクラッシュリカバリーの判定ルールを見てみましょう。
1. REDO ログ内のトランザクションが完了している場合、つまりコミット ID が既にある場合は、REDO ログ内のトランザクションのみが送信されます。準備が完了している場合は、対応するトランザクション バイナリ ログが存在し、完了しているかどうかを確認します。
a. 存在する場合は、トランザクションをコミットします。
ここで、時間 B で発生したクラッシュは状況 2(a) に対応し、トランザクションはクラッシュ回復プロセス中にコミットされます。
さて、引き続き 2 フェーズの提出を拡張していきましょう。
質問 1: MySQL はバイナリログが完了したことをどのようにして認識しますか?
回答: トランザクションのバイナリログは完全な形式です:
準備とコミットの両方が発生した場合REDO ログを直接送信します。
質問 3: 準備段階の REDO ログと完全な binlog は、再起動後に復元できるのはなぜですか?
回答: 実際、この質問は議論されるべきです。受信したデータはバックアップの一貫性に関連しています。時間 B、つまりバイナリ ログが書き込まれた後、MySQL がクラッシュします。この時点でバイナリ ログは書き込まれており、スレーブ ライブラリ (またはこのバイナリ ログを使用して復元されたライブラリ) によって使用されます。
したがって、このトランザクションはメイン データベースにも送信する必要があります。この戦略を使用すると、メイン データベースとスタンバイ データベースのデータの一貫性が保証されます。
質問 4: この場合、なぜ 2 段階の提出が必要なのでしょうか?まず REDO ログの書き込みを完了してから、binlog を書き込みます。クラッシュから回復するときは、両方のログが完全である必要があります。同じロジックですか?
回答: 実際、2 フェーズ コミットは分散システムの古典的な問題であり、MySQL に固有のものではありません。
これを行う必要性を説明するためにシナリオを挙げなければならないとすれば、それはトランザクションの耐久性の問題です。
InnoDB エンジンの場合、REDO ログの送信が完了した場合、トランザクションをロールバックすることはできません (ロールバックが許可されると、他のトランザクションの更新が上書きされる可能性があります)。また、REDO ログが直接送信され、その後バイナリログの書き込みに失敗した場合、InnoDB はロールバックできず、データとバイナリログは不整合になります。
二段階提出は全員にチャンスを与えるため、全員が「大丈夫」と言ったら一緒に提出します。
質問 5: 2 つのログを導入しない場合、2 段階の提出は必要ありません。クラッシュ回復をサポートし、アーカイブもサポートするには、binlog を使用するだけで十分ではないでしょうか?
回答: この質問を再度翻訳すると、バイナリログのみが保持され、送信プロセスは次のように変更できることになります。... -> "データをメモリに更新" -> 「バイナリログの書き込み」 -> 「トランザクションのコミット」、クラッシュから回復する機能も提供されますか? ######答えはいいえだ。
歴史的な理由
について言えば、InnoDB が MySQL のネイティブ ストレージ エンジンではないということです。 MySQL のネイティブ エンジンは MyISAM ですが、これはクラッシュ回復をサポートするように設計されていません。InnoDB が MySQL プラグインとして MySQL エンジン ファミリに加わる前、それはすでにクラッシュ回復とトランザクション サポートを提供するエンジンでした。
InnoDB を MySQL に接続した後、binlog にはクラッシュから回復する機能がないため、InnoDB の元の REDO ログを使用する方がよいことがわかりました。 導入理由について言えば、たくさんあります。質問で述べたように、クラッシュ回復プロセスの実装には binlog のみが使用されており、ここには REDO ログはありません。
図 2 binlog のみがクラッシュ リカバリをサポートします
このようなプロセスでは、binlog は依然としてクラッシュ リカバリをサポートできません。サポートされていない点についてお話します。binlog には「データ ページ」を復元する機能がありません。
図のマークされた位置、つまり binlog2 が書き込まれているがトランザクション全体がまだコミットされていない場合、MySQL がクラッシュします。
再起動後、エンジン内部トランザクション 2 はロールバックされ、それを補うために binlog2 を適用できます。ただし、トランザクション 1 については、システムはすでに送信が完了したとみなしているため、binlog1 は再度適用されません。
ただし、InnoDB エンジンは WAL テクノロジを使用し、トランザクションを実行するときは、メモリとログに書き込んだ後にトランザクションが完了します。後でクラッシュした場合は、ログを頼りにデータ ページを回復します。
つまり、図のこの位置でクラッシュが発生すると、トランザクション 1 も失われ、データ ページ レベルが失われる可能性があります。現時点では、データページの更新内容はビンログに記録されず、復元することはできません。
もし言いたいのであれば、binlog の内容を最適化して、データ ページに変更を記録できるようにすることはできますか?はい、しかしこれは実際には別の REDO ログを作成しているだけです。
したがって、少なくとも現在の binlog 機能ではクラッシュ回復をサポートできません。
質問 6: これを逆にして、binlog の代わりに REDO ログのみを使用することはできますか?
回答: クラッシュ回復の観点からのみであれば問題ありません。 binlog をオフにして 2 フェーズ コミットをなくすこともできますが、それでもシステムはクラッシュ セーフです。
しかし、業界のさまざまな企業の使用シナリオを見ると、公式の実稼働ライブラリでは binlog が常にオンになっていることがわかります。 binlog には REDO ログでは代替できない機能があるためです。
1 つはアーカイブです。 REDO ログはループで書き込まれます。最後まで書き込むと、最初に戻って書き続ける必要があります。この方法では、履歴ログを保持できず、REDO ログをアーカイブとして機能させることができません。
1 つは、MySQL システムが binlog に依存しているということです。 Binlog は MySQL が最初から持っている機能で、様々なところで使われています。その中で、MySQL システムの高可用性の基礎となるのがバイナリログレプリケーションです。
異種システム (一部のデータ分析システムなど) を導入している企業も多くあり、これらのシステムは自社のデータを更新するために MySQL binlog の使用に依存しています。 binlog がオフになっている場合、これらの下流システムは入力できなくなります。
つまり、MySQL の高可用性を含む多くのシステム メカニズムは現在 binlog に依存しているため、「カササギの巣を占領するハト」の REDO ログはまだ不可能です。生態系を発展させることがいかに重要であるかがわかります。
最後に、Ding Qi の「MySQL 実践講座 45」コラムに注目することをお勧めします。このコラムでは、Ding Qi が、トランザクション、インデックス、ロックなど、MySQL を学習するための主要な知識を整理するのに役立ちます。また、開発プロセス中に頻繁に遭遇する特定の問題についても分析して議論し、理解するのに役立ちます。問題の背後にある本質。 MySQL のコア テクノロジの詳細な説明と原則、および MySQL の 36 の一般的な問題点の分析が得られます。
ステートメント形式のバイナリログには最後に COMMIT があり、
行形式のバイナリログには最後に XID イベントがあります。
さらに、MySQL バージョン 5.6.2 以降では、binlog コンテンツの正確性を検証するために binlog-checksum パラメーターも導入されました。ディスク上の理由によりログの途中にエラーがある可能性がある binlog ログの場合、MySQL はチェックサムの結果を検証することでそれを見つけることができます。したがって、MySQL にはトランザクション バイナリログの整合性を検証する方法がまだあります。
質問 2: REDO ログと binlog はどのように関連していますか?
回答: これらには、XID と呼ばれる共通のデータ フィールドがあります。クラッシュリカバリ中に、REDO ログは次の順序でスキャンされます:
以上がMySQL の一般的なロギングの問題の概要の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。