ACID 特性を一度に全部実装するのではなく、 学習用 RDBMS として理解しやすい最小のトランザクション制御を段階的に導入する。
最初の目標は、単一接続・単一ライタの前提で
BEGIN / COMMIT / ROLLBACK、オートコミット、
クラッシュ時に壊れない atomic commit / rollback の最小経路を通すことにある。
2026-03-22 時点では、architecture.md には Transaction Manager を置く最終像があるが、
実装計画としてはまだ十分に分離されていない。
現在の状態は次の通り。
sqlcrate は最小 CRUD の parser を持つが、BEGIN / COMMIT / ROLLBACKは未対応querycrate は AST を正式入力として受ける境界が未整備storagecrate にはwal.rsの雛形があるが、回復戦略はまだ固定していない- 既存文書には「トランザクションは後回し」と「最終像では ACID を扱う」が混在している
この計画では、その間をつなぐ実装順序を固定する。
SQLite の公式文書では、暗黙トランザクションと
BEGIN / COMMIT / ROLLBACK を基本のトランザクション制御として説明している。
また、atomic commit の既定方式は rollback journal であり、
WAL は別モードとして後から選べる形になっている。
学習用実装でも、最初から WAL、checkpoint、複数接続、 MVCC、分離レベルをまとめて導入すると責務が広がりすぎる。 そのため、まずは rollback journal で Atomicity と Durability を理解し、 Isolation は単一接続・直列実行で単純化する。
sqlcrate でのBEGIN / COMMIT / ROLLBACKの最小 AST と parserquerycrate で transaction 文を受ける正式入口- セッション単位のトランザクション状態
- オートコミットと明示トランザクションの切り替え
- rollback journal ベースの commit / rollback / 起動時回復
- トランザクション文と CRUD を組み合わせた最小テスト
1 つのトランザクションに含まれる変更は、 全部反映されるか、全部取り消されるかのどちらかにする。
最初の段階では、型、構文、catalog、ページ不変条件の検証を既存レイヤーで行い、 トランザクション層は「途中状態を永続化しない」ことに集中する。
最初は単一接続・単一ライタに限定し、 トランザクション間の干渉を直列実行で避ける。 複数接続、MVCC、分離レベルは後続で扱う。
COMMIT 成功後の変更は、
クラッシュ後も回復できるよう journal とデータ反映の順序を固定する。
この計画の第一段階では、次だけを対象にする。
- SQL は
BEGIN,COMMIT,ROLLBACK - 実行モデルはオートコミット + 明示トランザクション
- 同時実行は単一接続、単一ライタ
- 回復方式は rollback journal
- 対象文は最小 CRUD と transaction 文の組み合わせ
SAVEPOINT,RELEASE,ROLLBACK TOBEGIN IMMEDIATE,BEGIN EXCLUSIVEなどの派生モード- 複数接続の同時実行
- MVCC
- 分離レベルの選択
- WAL と checkpoint
- 分散トランザクション
BEGIN;
INSERT INTO users VALUES (1, 'Alice');
UPDATE users SET name = 'Bob' WHERE id = 1;
COMMIT;
BEGIN;
DELETE FROM users WHERE id = 1;
ROLLBACK;オートコミット時は、BEGIN なしの各文を
暗黙トランザクションとして 1 文ずつ確定させる。
PostgreSQL と SQLite の公式文書と同様に、
明示的な BEGIN がない場合は各 SQL 文を 1 つのトランザクションとして扱う。
BEGIN の後は COMMIT か ROLLBACK が来るまで同じトランザクションを継続する。
トランザクション内で BEGIN を再度受けた場合はエラーにする。
最初は CLI や rdbms バイナリ上の 1 接続だけを前提にし、
トランザクション状態はセッションにぶら下げる。
- データページを書き換える前に、元の内容を journal へ退避する
COMMITでは journal とデータの永続化順序を守る- 途中で失敗したら journal から元の状態へ戻す
- 起動時に未完了 journal が残っていたら rollback してから通常起動する
SQLite の rollback journal も、 元データを別ファイルへ記録してから本体へ書き込むことで atomic commit を実現している。 学習段階ではこの考え方を単純化した最小版から始める。
WAL は reader / writer 並行性と checkpoint を伴うため、 rollback journal より概念が増える。 SQLite の公式文書でも、WAL は rollback journal と別の仕組みとして説明されている。 そのため、最初は rollback journal で commit 順序を理解し、 後から WAL へ広げる。
flowchart TB
subgraph SQL["sql crate"]
P[Parser]
AST[Statement AST]
end
subgraph QUERY["query crate"]
QB[AST Boundary]
EX[Executor]
end
subgraph TX["transaction layer"]
TM[Transaction Manager]
TS[Session Tx State]
end
subgraph ST["storage crate"]
JR[Rollback Journal]
PG[Page / Buffer / File]
end
P --> AST
AST --> QB
QB --> EX
EX --> TM
TM --> TS
TM --> JR
JR --> PG
sql::Statementに transaction 文を追加する- parser で
BEGIN / COMMIT / ROLLBACKを読めるようにする - この段階では派生モードや savepoint は読まない
querycrate の正式入口が transaction 文を受け取れるようにする- CRUD 文と transaction 文を同じ dispatcher で扱える形にする
- transaction 文自体は重い planning を要しないので、制御命令として executor へ渡す
- オートコミット中か、明示トランザクション中かを保持する
- 二重
BEGIN、COMMITなしのROLLBACKなどを状態エラーとして扱う
- 書換対象ページの旧イメージを journal に記録する
- journal の存在で未完了トランザクションを検出できるようにする
COMMITとROLLBACKの順序をテストで固定する
- 起動時に journal が残っていたら rollback を先に走らせる
- 回復後に通常処理へ進む
- journal 実装と transaction manager の責務境界を文書で固定する
- 後から WAL と checkpoint を足せるよう、API を rollback journal に過度に密結合させない
-
sqlcrate に transaction 文の AST を追加する - parser に
BEGIN / COMMIT / ROLLBACKの最小構文を追加する -
querycrate の境界で transaction 文を受け取れるようにする - CRUD 文と transaction 文を同じ executor 入口で扱えるようにする
- セッション単位のトランザクション状態を定義する
- オートコミット時の 1 文 1 トランザクションを固定する
- 明示トランザクション中の
COMMIT / ROLLBACKを実装する - rollback journal のファイル形式または最小記録単位を定義する
- 書換前ページを journal へ退避してから本体へ反映する順序を固定する
- 起動時に残留 journal を検出して rollback する回復処理を実装する
-
SAVEPOINT、WAL、複数接続をまだ扱わないことを文書で固定する - 将来 WAL へ進む判断基準を
docs/decisions.mdか後続計画へ残す
- parser テストで
BEGIN / COMMIT / ROLLBACKの正常系と異常系を固定する querycrate のテストで transaction 文が AST 境界を越えられることを固定する- executor テストでオートコミット時の 1 文確定を固定する
- 明示トランザクションで複数文を実行し、
COMMITで全反映されることを固定する - 明示トランザクションで複数文を実行し、
ROLLBACKで無効化されることを固定する - 擬似クラッシュ後に journal から回復できることを storage 側のテストで固定する
次の状態になれば、この計画の第一段階は完了とみなす。
BEGIN / COMMIT / ROLLBACKを parser から executor まで通せる- オートコミットと明示トランザクションの両方が動く
COMMIT後の変更が永続化され、ROLLBACK後の変更が残らない- 起動時に未完了 transaction を回復できる
- rollback journal と transaction manager の責務境界が文書で明確になっている
SAVEPOINTと部分 rollback を追加する- 複数接続を許可する前にロック戦略を決める
- rollback journal の次段階として WAL と checkpoint を検討する
- 必要になった段階で MVCC や分離レベルを検討する
- SQLite Transaction Control Syntax
- SQLite Isolation
- SQLite Atomic Commit
- SQLite Write-Ahead Logging
- PostgreSQL Transactions
- PostgreSQL Transaction Isolation