モチベーション
MySQL with InnoDB の一貫性が、なぜ・どのように実現されているのかを、できるだけ簡素にまとめたかったので、忘備録を兼ねて、作成。
本文
- MySQL with InnoDB (以下、単純に MySQL) は、BTree 構造でデータをディスクとメモリにおいて保持する RDB である。
- MySQL は、 Buffer Pool に対して読み書きを行うことで、操作を高速化する。
- Buffer Pool は、メモリ上に展開されたディスクデータの作業場である。
- Buffer Pool は、 Page 単位でディスクに対するキャッシュのような振る舞いをする。
- MySQL における Consistency は、 select 文については MVCC、更新については共有・排他ロックで実現される。
- MVCC とは、今現在の Buffer Pool の値ではなく、直近ある時点における値を読みめるようにするための制御のこと。
- 更新における共有・排他ロックは、更新の際にデータの走査に利用したインデックスの range と、発見されたレコードそれぞれに対して実施される。
- 更新文の中で、実際にデータを書き換えるために捜査した場合は排他ロックがかかり、ただ値を取得するだけの場合には共有ロックがかかる。
- ただ値を取得するだけ、とは、例えばサブクエリが該当する。
- Buffer Pool への更新は、 redo log によって永続化される。
- redo log は、 Buffer Pool への更新内容を記録した、 round robin なリングバッファとして機能するファイルである。
- これにより、 redo log を再度適用することで、更新内容を復元できる。
- Buffer Pool への更新は、まず Innodb Log Buffer (メモリ領域)に溜められ、ある一定程度たまると flush されてディスクに書き込まれる。
- 更新 transaction commit の際にも flush は行われる。
- redo log 上の通し番号を LSN (Log Sequence Number) という。
- トランザクション中の更新文は、 commit の前であっても redo log を作成する。
- roll back は、その rollback による変更が redo log に記述される。
- redo log は、 Buffer Pool への更新内容を記録した、 round robin なリングバッファとして機能するファイルである。
- Buffer Pool の内容自体をディスクへ同期することを checkpoint を作成する、という。
- MySQL は、 Buffer Pool のページに対して、そのページを最後に更新した際の LSN が、小さいものから順に checkpoint を作成していく。
- 永続化後は該当 redo log は不要になり、その領域が再度使える。
- redo log がリングバッファなのはこれが理由
- 永続化後は該当 redo log は不要になり、その領域が再度使える。
- ロールバックや MVCC での過去データは Undo ログによって実現される。
- Undo ログ一覧を History List と呼ぶ
- Undo ログは Buffer Pool として作成される。
- redo log も付与される。
- いらなくなった Undo ログを削除することをパージという。
- レコード削除は、最初は論理削除で、パージのタイミングで物理削除される。
最後に
実は、 fuzzy checkpointing がどうして consistent になるのか、はここでは述べられていないし、自分もいまいち理解できていないです。
具体的には、最小未反映 LSN のとある対象ページが、最大 LSN な変更の対象となっていた場合には、そのページを永続化するためにはその最小 LSN ~ 最大 LSN までの変更をすべてディスクに書き出し直さなければならないはずだが、しかしそういう自体が発生した場合の checkpointing がどのように行われていくかが、いまいち自分もわかっていないです。(そして文献もあまり見つからない。。)
誰か詳しい人などいれば、指摘していただけると幸いです m(_ _)m