目次
元に戻すログはどのようにフラッシュされる (ディスクに保存される) のでしょうか?
レコードをクエリするとき、バッファリングする必要があるのは 1 つのレコードのみですか?
「元に戻す」ページが変更された場合、対応するやり直しログを記録する必要がありますか?
REDO ログをディスクに書き込む必要があり、データもディスクに書き込む必要があります。なぜわざわざ行う必要があるのでしょうか。
binlog があるのに、なぜ redo ログが必要なのでしょうか?
データベース全体のデータを誤って削除した場合、REDO ログ ファイルを使用してデータを復元できますか?
SQL実行プロセス
以下に示すように、クエリ ステートメントが通過するプロセス、つまりレコードを「読み取る」プロセスがわかっています。
UPDATE t_user SET name = 'xiaolin' WHERE id = 1;
クエリ ステートメントと更新ステートメントの一連のプロセスも同じプロセスを実行します。
- クライアントは最初にコネクタを介して接続を確立し、コネクタはユーザーの ID を自動的に判断します。
- これは更新文なのでクエリ キャッシュを経由する必要はありませんが、テーブルに更新文があるとテーブル全体のクエリ キャッシュがクリアされてしまうため、クエリ キャッシュは役に立ちません。この関数は MySQL 8.0 で削除されました。
- パーサーは、字句解析を通じてキーワード更新、テーブル名などを識別し、構文ツリーを構築してから構文解析を実行して、入力ステートメントが MySQL 構文に準拠しているかどうかを判断します。
- プリプロセッサはテーブルとフィールドが存在するかどうかを判断します。
- オプティマイザーは実行計画を決定しますが、where 条件の ID は主キー インデックスであるため、ID インデックスを使用することを決定します。
- エグゼキューターは特定の実行を担当し、この行を見つけて更新します。
ただし、ステートメントを更新するプロセスには、UNDO ログ (ロールバック ログ)、REDO ログ (REDO ログ)、および binlog (アーカイブ ログ) の 3 種類のログが必要になります。
- undo ログ (ロールバック ログ) : トランザクションのアトミック性を実現する Innodb ストレージ エンジン層によって生成されるログで、主にトランザクション ロールバックや MVCC に使用されます。
- redo ログ (redo ログ) : Innodb ストレージ エンジン層によって生成されるログで、トランザクションの永続性を実装し、主に停電などの障害回復に使用されます。
- binlog (アーカイブ ログ) : サーバー層によって生成されるログで、主にデータのバックアップとマスター/スレーブ レプリケーションに使用されます。
なぜ元に戻すログが必要なのでしょうか?
「追加、削除、および変更」ステートメントを実行するとき、トランザクションを開始するために begin を入力したり、トランザクションを送信するためにコミットしたりはしませんが、MySQL は暗黙的にトランザクションを開始して「追加、削除、および変更」ステートメントを実行します。このようにして、「追加、削除、変更」ステートメントを実行した後、データベース テーブルで「追加、削除、変更」の結果を時間内に確認できることが保証されます。
ステートメントの実行時にトランザクションを自動的にコミットするかどうかは autocommit
パラメータによって決定され、デフォルトで有効になっています。したがって、update ステートメントの実行にもトランザクションが使用されます。
そこで、質問を考えてみましょう。トランザクションの実行中、トランザクションがコミットされる前に MySQL がクラッシュした場合、トランザクション前のデータにロールバックするにはどうすればよいですか?
トランザクション実行中にロールバックに必要な情報を毎回ログに記録しておけば、トランザクション実行の途中でMySQLがクラッシュした場合でも、トランザクション前のデータにロールバックできない心配がありません。ログはトランザクション前のデータにロールバックされます。
これを実現する仕組みが アンドゥログ(ロールバックログ)であり、トランザクションのACIDにおけるアトミック性(Aomicity)を保証します。
undo ログは、undo ロールバックに使用されるログです。トランザクションがコミットされる前に、MySQL はまず更新前のデータを UNDO ログ ファイルに記録します。トランザクションがロールバックされるときは、UNDO ログを使用してロールバックできます。以下に示すように:
InnoDB エンジンがレコードを操作 (変更、削除、追加) するときは常に、ロールバックに必要な次のような情報をすべて UNDO ログに記録する必要があります。
- レコードを挿入するときは、このレコードの主キー値を書き留める必要があります。これにより、後でロールバックするときに、この主キー値に対応するレコードを削除するだけで済みます。
- レコードを削除するときは、後でロールバックするときにこれらの内容で構成されるレコードをテーブルに挿入できるように、レコードのすべての内容を書き留める必要があります。
- レコードを更新するときは、ロールバック時にこれらの列を古い値に更新できるように、更新された列の古い値を記録します。
ロールバックが発生すると、アンドゥ ログ内のデータが読み取られ、その逆の操作が実行されます。たとえば、レコードが削除されると、レコードの内容がアンドゥ ログに記録され、ロールバック操作が実行されると、アンドゥ ログのデータが読み取られて、挿入操作が実行されます。
操作ごとに記録する必要がある内容が異なるため、操作の種類(変更、削除、追加)によって生成されるアンドゥログの形式も異なりますが、各操作の具体的なアンドゥログ形式については詳しく紹介しません。はい、ご興味がございましたら、ご自身で調べてみてください。
レコードの各更新操作によって生成される元に戻すログ形式には、roll_pointer ポインターと trx_id トランザクション ID が含まれます。
- trx_id を通じて、どのトランザクションがレコードを変更したかを知ることができます。
- これらの元に戻すログは、roll_pointer ポインタを介してリンク リストに連結できます。このリンク リストはバージョン チェーンと呼ばれます。
バージョンチェーンは以下のとおりです。
また、アンドゥログには ReadView + アンドゥログ による MVCC (マルチバージョン同時実行制御) を実現する機能もあります。
「読み取りコミット」および「反復読み取り」分離レベルのトランザクションの場合、スナップショット読み取り (通常の選択ステートメント) は読み取りビュー + 元に戻すログを通じて実装されます。違いは読み取りビューの作成タイミングにあります。
- 「読み取りコミット」分離レベルでは、選択ごとに新しい読み取りビューが生成されます。これは、トランザクション中に同じデータが複数回読み取られる場合、処理中に他のデータが存在する可能性があるため、前後に 2 回読み取られたデータに一貫性がない可能性があることも意味します。トランザクションがレコードを変更し、トランザクションをコミットしました。
- 「Repeatable Read」分離レベルは、トランザクションの開始時に読み取りビューを生成し、トランザクション全体でこの読み取りビューを使用します。これにより、トランザクション中に読み取られるデータは、トランザクションが開始される前のすべてのレコードになります。
これら 2 つの分離レベルは、「トランザクションの読み取りビューのフィールド」と「レコード内の 2 つの非表示列 (trx_id と roll_pointer)」の比較を通じて実装されます。表示される行が満たされない場合、UNDO ログのバージョン チェーンは次のようになります。可視性を満たすレコードを検索し、同じレコードにアクセスする際の同時トランザクションの動作を制御することを、MVCC (Multiple Version Concurrency Control) と呼びます。
したがって、Undo ログには 2 つの主要な機能があります。
- トランザクションのロールバックを実装し、トランザクションのアトミック性を確保します。トランザクション処理中にエラーが発生した場合、またはユーザーが ROLLBACK ステートメントを実行した場合、MySQL はアンドゥ ログ内の履歴データを使用して、データをトランザクション開始前の状態に復元できます。
- MVCC (Multiple Version Concurrency Control) を実装する際の重要な要素の 1 つ。MVCC は ReadView + undo ログを通じて実装されます。アンドゥ ログには、レコードごとに履歴データの複数のコピーが保存されます。MySQL がスナップショット読み取り (通常の選択ステートメント) を実行すると、アンドゥ ログのバージョン チェーンに従い、トランザクションの読み取り内の情報に基づいて可視性を満たすレコードを見つけます。ビュー。
元に戻すログはどのようにフラッシュされる (ディスクに保存される) のでしょうか?
UNDO ログとデータ ページのフラッシュ戦略は同じですが、どちらも永続性を確保するために REDO ログが必要です。
バッファプールには元に戻すページがあり、元に戻すページへの変更も再実行ログに記録されます。REDO ログは毎秒ディスクをフラッシュし、トランザクションが送信されたときにもディスクをフラッシュします。データ ページとアンドゥ ページは永続性を確保するためにこのメカニズムに依存しています。
なぜバッファプールが必要なのでしょうか?
MySQL データはディスクに保存されるため、レコードを更新する場合は、まずディスクからレコードを読み取り、次にメモリ内のレコードを変更する必要があります。このレコードを変更した後、ディスクに直接書き戻すことを選択するべきですか、それともキャッシュすることを選択するべきですか?
もちろん、次回クエリ ステートメントがこのレコードにヒットしたときに、ディスクからデータを取得する必要なく、キャッシュ内のレコードを直接読み取ることができるように、キャッシュすることをお勧めします。
この目的を達成するために、Innodb ストレージ エンジンは、データベースの読み取りおよび書き込みパフォーマンスを向上させるバッファ プール (バッファ プール)を設計しました。
バッファープーをした後:
- データを読み取るとき、データがバッファ プールに存在する場合、クライアントはバッファ プール内のデータを直接読み取ります。それ以外の場合は、ディスクからデータを読み取ります。
- データを変更する場合、データがバッファ プールに存在する場合は、バッファ プール内のデータが配置されているページを直接変更し、そのページをダーティ ページとして設定します (このページのメモリ データはデータと一致しなくなりました)ディスクの容量を減らすため、I/O では、ダーティ ページはすぐにディスクに書き込まれず、その後、バックグラウンド スレッドが適切な時間を選択して、ダーティ ページをディスクに書き込みます。
バッファプールは何をキャッシュしますか?
InnoDB は、ディスクとメモリ間の対話の基本単位としてページを使用して、保存されたデータをいくつかの「ページ」に分割します。ページのデフォルト サイズは 16 KB です。したがって、バッファプールも「ページ」ごとに分割する必要があります。
MySQL が起動すると、InnoDB はバッファ プールの連続メモリ領域を申請し、16KB
デフォルト サイズに従ってページを複数のページに分割します。バッファ プール内のページは キャッシュ ページ と呼ばれます。現時点では、これらのキャッシュ ページは空きですが、後でプログラムが実行されると、ディスク上のページがバッファ プールにキャッシュされます。
したがって、MySQL を最初に起動すると、使用される仮想メモリ空間は大きいが、使用される物理メモリ空間は非常に小さいことがわかります。これは、オペレーティング システムがこれらの仮想メモリにアクセスした後でのみページ フォールト割り込みをトリガーするためです。物理メモリを適用し、仮想アドレスと物理アドレス間のマッピング関係を確立します。
バッファ プールには、「インデックス ページ」と「データ ページ」のキャッシュに加えて、アンドゥ ページ、挿入キャッシュ、アダプティブ ハッシュ インデックス、ロック情報なども含まれます。
「元に戻す」ページには何が記録されますか?
トランザクションが開始された後、InnoDB レイヤーがレコードを更新する前に、対応する Undo ログが最初に記録される必要があります。更新操作の場合は、更新された列の古い値が記録される必要があります。が生成され、元に戻すログがバッファ プールに書き込まれます。 の元に戻すページ。
レコードをクエリするとき、バッファリングする必要があるのは 1 つのレコードのみですか?
いいえ。
レコードをクエリすると、InnoDB はデータのページ全体をバッファ プールにロードします。ページをバッファ プールにロードした後、ページ内の「ページ ディレクトリ」を通じて特定のレコードを見つけます。
なぜREDOログが必要なのでしょうか?
確かにバッファ プールによって読み取りと書き込みの効率が向上しますが、ここで問題が発生します。バッファ プールはメモリに基づいており、メモリは常に信頼性が低くなります。停電および再起動が発生した場合、時間が経っていないダーティ ページ データは失われます。ディスクに書き込まれるファイルは失われます。
停電によるデータ損失を防ぐために、レコードを更新する必要がある場合、InnoDB エンジンはまずメモリを更新し (そしてダーティ ページとしてマークし)、次にこのページへの変更を redo の形式で記録します。ログが表示され、現時点で更新は完了しています。
その後、InnoDB エンジンは、適切なタイミングでバッファ プールにキャッシュされたダーティ ページをバックグラウンド スレッドによってディスクにフラッシュします (WAL ( Write-Ahead Logging) テクノロジ)。
WAL テクノロジは、MySQL の書き込み操作がすぐにディスクに書き込まれるのではなく、ログが最初に書き込まれ、その後適切なタイミングでディスクに書き込まれることを意味します。
REDOログとは何ですか?
REDO ログは、特定のデータ ページに加えられた変更を記録する物理ログです。たとえば、AAA 更新は、XXX 表スペース内の YYY データ ページの ZZZ オフセットに対して行われます。トランザクションが実行されるたびに、このようなメッセージが表示されます。または複数の物理ログ。
トランザクションがコミットされると、最初に REDO ログをディスクに永続化するだけでよく、バッファ プールにキャッシュされたダーティ ページ データがディスクに永続化されるまで待つ必要はありません。
システムがクラッシュした場合、ダーティ ページ データは保持されませんが、REDO ログは保持されており、MySQL を再起動すると、REDO ログの内容に基づいてすべてのデータを最新の状態に復元できます。
「元に戻す」ページが変更された場合、対応するやり直しログを記録する必要がありますか?
ニーズ。
トランザクションが開始された後、InnoDB レイヤーがレコードを更新する前に、対応する Undo ログが最初に記録される必要があります。更新操作の場合は、更新された列の古い値が記録される必要があります。が生成され、元に戻すログがバッファ プールに書き込まれます。 の元に戻すページ。
ただし、[元に戻す] ページがメモリ内で変更された後は、対応する REDO ログを記録する必要があります。
REDO ログと UNDO ログの違いは何ですか?
これら 2 種類のログは InnoDB ストレージ エンジンに属しており、それらの違いは次のとおりです。
- REDO ログには、トランザクションの「完了後」のデータ ステータスと更新された値が記録されます。
- アンドゥログには、このトランザクションの「開始前」のデータ状態と更新前の値が記録されます。
トランザクションがコミットされる前にクラッシュが発生した場合、トランザクションは再起動後に UNDO ログを通じてロールバックされ、トランザクションがコミットされた後にクラッシュが発生した場合、トランザクションは再起動後に REDO ログを通じて復元されます。
したがって、InnoDB は、REDO ログと WAL テクノロジを使用して、データベースが異常に再起動した場合でも、以前に送信されたレコードが失われないことを保証できます。この機能は クラッシュ セーフ(クラッシュ リカバリ) と呼ばれます。REDO ログにより、トランザクションの 4 つの主要な特性の耐久性が保証されていることがわかります 。
REDO ログをディスクに書き込む必要があり、データもディスクに書き込む必要があります。なぜわざわざ行う必要があるのでしょうか。
REDO ログの書き込み方法は追加操作を使用するため、ディスク操作はシーケンシャル書き込みであり、データの書き込みは最初に書き込み場所を見つけてからディスクに書き込む必要があるため、ディスク操作はランダム書き込みになります。
ディスクへの「シーケンシャル書き込み」は「ランダム書き込み」よりもはるかに効率的であるため、ディスクへの REDO ログ書き込みのオーバーヘッドは小さくなります。
なぜ「順書き」のほうが「ランダム書き」より速いのかというと、ノートに例えると、ページを順番に書いていくほうが、対応するページを見つけて一字一句書くより断然早いです。
これも WAL テクノロジーの利点と言えます。MySQLの書き込み操作がディスク上での「ランダム書き込み」から「シーケンシャル書き込み」に変更され、ステートメントの実行パフォーマンスが向上します。これは、MySQL の書き込み操作がすぐにディスクに更新されるのではなく、まずログに記録され、その後適切なタイミングでディスクに更新されるためです。
この時点で、REDO ログがなぜ必要なのかという質問に対して 2 つの答えがあります。
- トランザクション耐久性を実装し、MySQL をクラッシュセーフにし、MySQL がいつでも突然クラッシュした場合でも、再起動後に以前に送信されたレコードが失われないようにします。
- 書き込み操作を「ランダム書き込み」から「シーケンシャル書き込み」に変更して、 MySQL のディスクへの書き込みパフォーマンスを向上させます。
REDO ログはいつフラッシュされますか?
REDO ログ バッファにキャッシュされた REDO ログはまだメモリ内にありますか? いつディスクにフラッシュされますか?
主に以下のような機会があります。
- MySQL が正常にシャットダウンされたとき。
- REDO ログ バッファに記録された書き込み量が REDO ログ バッファのメモリ領域の半分を超えると、ディスク ドロップがトリガーされます。
- InnoDB のバックグラウンド スレッドは、REDO ログ バッファを毎秒ディスクに保存します。
- トランザクションがコミットされるたびに、REDO ログ バッファにキャッシュされた REDO ログはディスクに直接保存されます (この戦略は、後述する innodb_flush_log_at_trx_commit パラメータによって制御できます)。
なぜビンログが必要なのでしょうか?
前に紹介した undo ログと redo ログはどちらも Innodb ストレージ エンジンによって生成されます。
MySQL が更新操作を完了すると、サーバー層も binlog を生成し、後でトランザクションが送信されると、トランザクションの実行中に生成されたすべての binlog が binlog ファイルに書き込まれます。
binlog ファイルは、データベース テーブル構造のすべての変更とテーブル データの変更を記録するログであり、SELECT 操作や SHOW 操作などのクエリ操作は記録しません。
binlog があるのに、なぜ redo ログが必要なのでしょうか?
この問題は MySQL タイムラインに関連しています。
当初、MySQL には InnoDB エンジンはなく、MySQL 独自のエンジンは MyISAM でしたが、MyISAM にはクラッシュセーフ機能がなく、binlog ログはアーカイブにしか使用できませんでした。
InnoDB は、プラグインの形式で MySQL を導入したもう 1 つの会社ですが、binlog のみに依存するとクラッシュ セーフ機能がないため、InnoDB は REDO ログを使用してクラッシュ セーフ機能を実現します。
REDO ログと binlog の違いは何ですか?
これら 2 つのログには 4 つの違いがあります。
1. 適用可能なさまざまなオブジェクト:
- Binlog は、MySQL のサーバー層によって実装されるログであり、すべてのストレージ エンジンで使用できます。
- REDO ログは、Innodb ストレージ エンジンによって実装されるログです。
2. さまざまなファイル形式:
- Binlog には、STATEMENT (デフォルトの形式)、ROW、および MIXED の 3 つの形式タイプがあり、違いは次のとおりです。
- ステートメント: データを変更するすべての SQL は binlog に記録され (論理操作の記録に相当するため、この形式では binlog を論理ログと呼ぶことができます)、マスター/スレーブ レプリケーションのスレーブ側は、それに基づいてそれを再現します。 SQL ステートメント。しかし、STATEMENT には動的な関数の問題があります。たとえば、uuid 関数や now 関数を使用する場合、メイン ライブラリで実行した結果がスレーブ ライブラリで実行した結果と異なります。このような関数はいつでも変更されると、コピーされた関数が発生します。データに一貫性がないこと。
- ROW: 行データが最終的にどのように変更されたかを記録します (この形式のログは論理ログとは言えません)。STATEMENT での動的関数には問題はありません。ただし、ROW の欠点は、データ行ごとの変更結果が記録されることです。たとえば、バッチ更新ステートメントを実行すると、データ行が更新されると同じだけ多くのレコードが生成され、binlog ファイルも作成されます。 STATEMENT 形式では、更新ステートメントは 1 つだけ記録されます。
- MIXED: STATEMENT モードと ROW モードが含まれており、さまざまな状況に応じて ROW モードと STATEMENT モードが自動的に使用されます。
- REDO ログは物理ログであり、XXX 表スペース内の YYY データ・ページの ZZZ オフセットでの AAA 更新など、特定のデータ・ページに加えられた変更を記録します。
3. さまざまな書き込み方法:
- binlog は追記書き込みです。ファイルがいっぱいになると、新しいファイルが作成されて書き込みが継続されます。以前のログは上書きされず、ログ全体が保存されます。
- REDO ログはループで書き込まれ、ログ領域のサイズは固定されており、いっぱいになると最初から開始され、ディスクにフラッシュされていないダーティ ページ ログが保存されます。
4. さまざまな用途:
- binlog はバックアップとリカバリ、マスター/スレーブ レプリケーションに使用されます。
- REDO ログは、停電やその他の障害の回復に使用されます。
データベース全体のデータを誤って削除した場合、REDO ログ ファイルを使用してデータを復元できますか?
REDO ログ ファイルを使用して復元することはできません。復元には binlog ファイルのみを使用できます。
REDO ログ ファイルは周期的に書き込まれるため、ログは書き込み中に消去されます。ディスクにフラッシュされていないデータの物理ログのみが記録されます。ディスクにフラッシュされたデータは REDO ログ ファイルから消去されます。 。
binlog ファイルには、ログの全量が保存されます。つまり、すべてのデータ変更が保存されます。理論的には、binlog に記録されたデータを復元できる限り、データベース データ全体が誤って削除された場合は、binlog ファイルを使用する必要があります。ファイルを復元します。