Transactional write の調査: MySQL 編

引き続き trx write の実装について調べていく。 今回は MySQL を見ている。

MySQL はめちゃくちゃたくさんログを書いているしどれが何をしているのかというのは初見ではわかりにくい。 実際にトランザクションに関係するログは、innodb_log_* 系で設定する redo log と、double write buffer、undo log である。

ここでは主に redo について述べていく。 MySQLredo log の実態は mini-transaction (mtr) と呼ばれる構造体からなっている。 mtrSQL レベルのトランザクションではなく、内部的に実行するデータ変更操作を記録するためのもののようだ。

mtr0types.h ではどういう操作を記録しているかが enum として定義されている。

https://github.com/mysql/mysql-server/blob/5.7/storage/innobase/include/mtr0types.h#L54

例えば MLOG_REC_INSERT を見てみると、page_cur_insert_rec_write_log で使われている。 この関数の末尾では mtr の内部バッファにレコードをコピーしている。

https://github.com/mysql/mysql-server/blob/5.7/storage/innobase/page/page0cur.cc#L1128

ということで、mtr はページレベルではなく、内部操作に必要十分なデータのみを記録しているようだ。

実際の mtr のディスクへの書き出しは、様々なタイミングで行われているが、 SQL レベルの commit では innodb_flush_log_at_trx_commit が 1 ならば強制的に sync される。 また MySQL 起動時に定期的に書き出すスレッドが作成されている。

mtr は論理レベルのログなので、パーシャルライトが起こりうる。 これを防止するための機構が double write buffer である。

さて、mtrSQL レベルトランザクションの関係だが、雑に見た感じだと、 SQL の COMMIT が実行されると undo log がパージされることで rollback されないようにしているように見えた。