CLOG
CLOGのフォーマット
CLOGではトランザクションごとのコミット状態のデータを持つ。ひとつのトランザクションにつき2ビットしか使わない。要するに状態は4種類だけということ。とりうる状態は次のように定義されている。
#define TRANSACTION_STATUS_IN_PROGRESS 0x00 #define TRANSACTION_STATUS_COMMITTED 0x01 #define TRANSACTION_STATUS_ABORTED 0x02 #define TRANSACTION_STATUS_SUB_COMMITTED 0x03
ただし、TRANSACTION_STATUS_IN_PROGRESSは初期状態のこと。これを書き込んでいるところはなかった。ふつーに疑問なのはSUB_ABORTEDはいらないのだろうか?サブトランザクションの概念が把握できていないのでなんともいえない。
トランザクションIDから、どのファイルの何番目のページの何バイト目のどの2ビットを使うかが一意に決まるロジックになっている。
1バイトに限って見てみる。最初のトランザクションがコミットされると右から数えて1ビット目と2ビット目が使用される。
00000001
次のトランザクションもコミットされると右から数えて3ビット目と4ビット目が使用される。
00000101
その次のトランザクションがロールバックされるとと右から数えて5ビット目と6ビット目が使用される。
00100101
CLOGとWAL
チェックポイントで共有バッファやCLOGがディスクにフラッシュされる前にクラッシュする次のようなケースを考えてみた。
1. BEGIN; 2. INSERT; … WALプロトコルによりタプルを追加したことが記録される 3. COMMIT; … WALプロトコルによりコミットされたことが記録される 4. チェックポイントの前にクラッシュ
リカバリで、INSERTで追加されたタプルは他のトランザクションから見えるようにしなければいけない。しかし、CLOGが失われてしまっているのだから、INSERTを行ったトランザクションがコミットされたかどうかわからないじゃないか、と最初考えた。でも、これはおかしい。WALログにはトランザクションがコミットされたことがちゃんと記録されている。では、コミットされたかどうかを確認するのにCLOGをみたりWALログをみたり場合わけするのか?
そうではない。どうやら、リカバリ時にデータの復旧よりも先にWALログからCLOGが復旧される(コミット処理やロールバック処理が実行されてCLOGが作成される)ようだ。そして、その後でデータが復旧されるが、コミットされたかどうかはCLOGをみて判断すると推測できる(この判断が前のエントリで述べたMVCCのチェックでされるのか、別のところでなされるのかは未確認)。CLOGがWALログから復旧されるという観点になかなか気づかなかった。