LoginSignup
42
23

More than 1 year has passed since last update.

MySQLのbinlogとredo logについて

Last updated at Posted at 2019-05-11

MySQLにbinlogとredo logの二つの重要なログシステムがあります。本文では、この二つのログの仕組みについて説明します。
#1.基本知識
MySQLは、SQLの解析と実行する機能を実現するServer層とデータアクセス機能を提供するストレージエンジン層で構成されています。ストレージエンジンには、MyISAM、InnoDB、Memoryなどが存在します。

binlogは、Server層が出力するログです。redo logは、InnoDBエンジンが出力するログです。二つのログは、ともにDBテーブル更新時に出力されます。

ディスクアクセスに時間がかかるため、InnoDBエンジンがメモリ上でレコードを更新し、redo log bufferに記録したら、レコード更新操作が完了とします。この仕組みは、WAL(Write Ahead Logging)といいます。別の専用スレッドが適当のタイミングでredo log bufferの内容をディスクにあるredo logファイルに書き出します。redo logファイルの個数とサイズが固定であり、ループで使用します。最後のファイルが一杯になったら、最初のファイルに戻って、再利用します。MySQLが異常終了して再起動する時に、redo logを用いて、コミット済みでディスクに保存されていないレコードのデータを復元します。

binlogは、レコードの更新内容を保存します。誤って削除したデータを復元する場合、binlogを利用します。データベースのバックアップをベースに、バックアップ時点から指定時点の間のbinlogを適用することで、指定時点のデータを復元できます。また、マスタスレーブ構成で2つ以上のデータベースサーバが存在する場合、マスタサーバからスレーブサーバにbinlogの内容を転送します。スレーブサーバがbinlogを適用して、マスタサーバのデータと一致性を保ちます。

binlogとredo logの違いは、下表で示します。
image.png

#2.更新SQL文の実行プロセス
下図にて、更新SQL文の実行プロセスを説明します。
image.png

上図の最後の三つのステップでredo logとbinlogを2フェースコミットの形で更新します。これは、redo logとbinlogの一致性を保つための仕組みです。
MySQLが再起動する時に、redo logをスキャンして、コミット状態であれば、redo logに記述されたレコードの更新内容をコミットします。prepared状態であれば、まずbinlogの状態をチェックします。該当binlogが完了していない場合は(上図①のタイミングでクラッシュ)、redo logに記述されたレコードの更新内容をロールバックします。該当binlogが完了している場合は(上図②のタイミングでクラッシュ)、更新内容をコミットします。

※statementモードのbinlogの最後に「COMMIT」句があり、rowモードのbinlogの最後に XIDイベントが存在します。MySQL 5.6.2以後のバージョンでは、binlog-checksumを導入しました。checksumの値を検証してbinlogが完了しているか判定できます。
※トランザクションにトランザクションIDが割り振られて、トランザクションIDがredo logとbinlogに記録されます。

#3.redo logの書出し
redo logに三つの状態があります。下図にて三つの色のあるボックスで表します。

image.png

1.redo log buffer。MySQLプロセスのメモリに存在します。
2.Page cache。ファイルシステムのCache(メモリ)に存在します。writeシステムコールの呼び出しでデータをPage Cacheに書き出します。
3.Hard Disk。ハードディスクに存在します。fsyncシステムコールを呼び出して、データをHard Diskに保存します

InnoDBにバックグランドスレッドがあって、1秒毎に、redo log bufferにあるデータをwriteの呼出しでPage cacheに書出し、次にfsyncを呼び出してHard Diskに保存します。
まだコミットしていないトランザクションの更新データもredo log bufferにあるので、同じタイミングでHard Diskに保存されます。

上記以外、以下の場合でも未コミットデータがディスクに書き出されます。
1.redo log bufferの使用済みサイズがパラメータ「innodb_log_buffer_size」の半分になる直前に、バックグランドスレッドがディスクにredo logを書出します。ただ、この場合、writeのみを呼び出し、fsyncを呼び出しません。
2.並行実行のトランザクションがコミットされた場合、パラメータ「innodb_flush_log_at_trx_commit」の値が「1」であれば、redo log bufferの内容がDBに書き出されます。

42
23
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
42
23