mysqlでの更新SQLの実行方法
redo log
すべての更新操作がディスクに書き込まれる必要があり、ディスクも対応する行を見つけて更新する必要がある場合、プロセス全体の IO コストとルックアップ コストが高くなります。この問題を解決するために、MySQLの設計者はWALと呼ばれる技術を使用しました。WALの完全な名前はWrite-Ahead Loggingです。レコードが更新される必要がある場合は、InnoDBエンジンは、まず内部のREDOログにレコードを書き込み、メモリを更新し、この時間も更新が完了です。InnoDBエンジンは、適切な時間にされ、操作レコードは、ディスクに更新され、この更新は、多くの場合、システムが比較的アイドル時に行われます。例えば、4つのファイルのセットとして構成することができ、各ファイルのサイズは1GBで、合計4GBの操作を記録することができます。最初から書き込み、ループの最後まで書き込み最初に戻ります。
binlog
1つはサーバ層で、主にMySQLの機能レベルで行われ、もう1つはエンジン層で、ストレージ関連の特定の事柄を担当します。Redo ログは InnoDB エンジン固有のログであり、サーバ レイヤには binlog (アーカイブ ログ) と呼ばれる独自のログがあります。
なぜ2つのログがあるのですか?
MySQLには当初InnoDBエンジンがなく、MySQLに付属していたエンジンはMyISAMでしたが、MyISAMにはクラッシュセーフ機能がなく、binlogログはアーカイブにしか使えないからです。InnoDBは他社がプラグインとしてMySQLに導入したもので、binlogだけに依存するのはクラッシュセーフではないので、InnoDBは別のロギングシステムであるREDOログを使用してクラッシュセーフ機能を実現しています。
これら2つのログには3つの違いがあります。
- redoログはInnoDBエンジンに固有で、binlogはMySQLサーバ層に実装され、すべてのエンジンで使用できます。
- redoログは物理的なログで、記録は「データ⻚にどのような変更が加えられたか」、binlogは論理的なログで、記録は「cフィールドのID = 2のこの行に1を加えた」のようなステートメントの元のロジックです。
- redoログは、書き込みのサイクルです、スペースがなくなるように固定されます。append write "は、binlogファイルが一定サイズ書き込まれると次のファイルに切り替わり、前のログを上書きしないという意味です。
上記2種類のログを組み合わせることで、更新の実行プロセスを把握することができます。
IDは主キーであり、エンジンはこの行を見つけるために直接ツリーを検索します。ID=2 の行がすでにメモリ内にあるツリーにある場合、その行は直接エクゼキュータに返されます。
ID=2 行があるデータ ⻚がすでにメモリ内にある場合は、直接エクゼキュータに返されます。そうでない場合は、まずディスクからメモリに読み込んでから返す必要があります。
そうでない場合は、まずディスクからメモリに読み込んでから返します。エクゼキュータは、エンジンから与えられたデータ行を取得し、例えばNであったものがN+1になるように値を1に加え、新しいデータ行を取得します。
エンジンは新しいデータ行をメモリに更新し、同時に更新操作を準備状態のREDOログに記録します。その後、エクゼキュータは実行が完了し、トランザクションをコミットする準備ができたことを通知されます。
エクゼキュータは操作のbinlogを生成し、binlogをディスクに書き込みます。
エクゼキュータはエンジンのコミット トランザクション インターフェイスを呼び出し、エンジンは書き込まれたばかりのREDOログをコミット状態に変更し、更新は完了します。
ここでは、この更新文の実行のフローチャートを示します。薄い色のボックスはInnoDB内で実行されることを示し、濃い色のボックスはエクゼキュータ内で実行されることを示します。
どうすれば半月の間にデータベースを元の状態に戻すことができますか?
binlogはすべての論理操作を記録し、"追記 "として書き込まれます。DBAが半月以内にデータベースを復旧できると約束した場合、バックアップシステムは過去半月のすべてのビンログを保持し、システムは定期的にデータベース全体のバックアップを行います。
まず、最新のフルバックアップを探し、運が良ければ昨晩のものであるかもしれません。)
次に、バックアップの時点から順番にバックアップのビンログを取り出し、昼に間違ってテーブルを削除した時点まで再生します。
なぜログに「2段階コミット」が必要なのですか?
REDOログが最初に書き込まれ、その後にBINLOGが書き込まれます。REDOログが書き込まれ、BINLOGがまだ終了していないときにMySQLのプロセスが異常再起動した場合を想定しています。先ほど言ったように、REDOログが書き込まれた後は、システムがクラッシュしてもデータをリカバリすることができるので、この行のcの値はリカバリ後に1になります。 しかし、REDOログが書き込まれる前にbinlogがクラッシュするので、その時のbinlogにはこのステートメントの記録はありません。そのため、後でログをバックアップしても、保存されたbinlogにはこのステートメントはありません。 そして、このステートメントのビンログが失われたために、このビンログを使って一時的なライブラリを復元する必要がある場合、一時的なライブラリにはこの更新がなくなり、復元された行のcの値は元のライブラリの値とは異なる0になります。
binlogを先に書いてからREDOログを書くと、binlogを書いた後にクラッシュした場合、REDOログはまだ書かれていないので、クラッシュが回復した後のトランザクションは無効になり、この行のcの値は0になります。そのため、後で復旧するためにbinlogを使用すると、トランザクションが1つ増え、復旧した行のcの値は1になり、元のリポジトリの値とは異なります。