まえがき
前回は自トランザクションと他トランザクションからの見え方を制御する可視性制御、という概念とその実装方針について記載しました。今回は、トランザクション内で複数の変更操作を実行した場合に、どのようにそれらの変更履歴を積み重ねていくかについて考えていきます。gitでいうならローカルブランチに対して複数回コミットをするときのイメージです。
ローカルデータ領域のデータ構造
まず初めに、前回のローカルデータ領域のデータ構造は、共有データ領域と全く同じデータ構造をしていました。しかし、各変更操作(INSERT/UPDATE/DELETE)ごとに、参照用カラムインデックスの作り方が変わってきます。そのため、ローカルデータ領域にはどのクエリで、どういう操作が実行されたかも保持するようにします。
複数回の変更操作
1トランザクション内で、複数の変更操作をしたことを考える。ローカルデータ領域に対しては、変更操作が行われた順に操作の履歴を積み重ねていかなければいけない。なぜなら、下記のような変更をしたとする。
- りんごの値段を120円に変更する
- りんごの値段を90円に変更する
この操作をするとりんごの値段は90円になっているはずである。しかしもし、この操作を逆順に実行した場合、りんごの値段は120円になってしまう。トランザクション内ではやはり、クエリ実行の順序を保って操作をしなければならず、そうなるように可視性制御もしなければならない。
そういうわけで、クエリごとにクエリIDを発行し、トランザクション内でのクエリの実行順序を記録する。トランザクションごとに、クエリの実行順にクエリIDをリストのお尻に足していく。こうすれば、トランザクション内で、A→B→Cの順でクエリが実行されたことがわかる。これを管理するシステムテーブルはms_tx_queryと名付けておく。
続いて、ローカルデータ領域は、クエリIDをキーとして、そのクエリの操作と変更データを持つテーブルにする。
INSERTの場合は、オブジェクトIDと挿入したデータを保持。
UPDATEの場合は、更新するオブジェクトIDと更新前の値と更新後の値を保持。
DELETEの場合は、削除したオブジェクトIDとそのデータを保持
自トランザクション内でSELECTする
自トランザクション内でSELECTするときは、上記のローカルデータ領域の更新を、それらが実行された順番で共有データに対して適用して参照用テーブルを作成する。SELECTが発行されるたびに、共有データに対して更新操作を適用して参照用のテーブルを作るのはコストが大きいが、それはバッファを設計するときに考慮する。
まとめ
複数回の変更操作に対しても可視性制御を行うために、ローカルデータ領域のデータ構造を説明しました。最後に、トランザクションをCOMMITしたときに共有データ領域への書き込みフローについて明日記載します。