MVCC えむぶいしーしー
同時実行制御スナップショットロックトランザクションバキュームPostgreSQL
MVCCについて教えて
簡単に言うとこんな感じ!
MVCCは「データの過去バージョンを複数保持して、読む人は古いコピーを見せる」仕組みだよ! 図書館で本を修正中でも、来館者には元の本のコピーを渡せるから「修正が終わるまで待って」とならない。読み書きが互いにブロックしない高速DBの秘密なんだ!
MVCCとは
MVCC(Multi-Version Concurrency Control:多版型同時実行制御)とは、データの複数バージョンを同時に保持することで「読み取りと書き込みが互いをブロックしない」並行処理を実現する技術です。PostgreSQL・Oracle・MySQL InnoDB・MongoDB・CockroachDBなど、現代の主要なDBMSの多くが採用しています。
従来の「ロックのみに依存する方式」では、あるトランザクションがデータを更新中に別のトランザクションが同じデータを読もうとすると待機が発生します。MVCCでは更新を「既存行を上書き」するのではなく「新しいバージョンを追加」する方式で処理するため、読み取りトランザクションはその時点で有効な古いバージョンを参照し続けられます。結果として、読み取りが書き込みをブロックせず、書き込みも読み取りをブロックしないという高い同時実行性が実現します。
トレードオフとして、古いバージョンのデータが蓄積するため、不要になったバージョンを定期的にクリーンアップする処理(PostgreSQLのVACUUMなど)が必要になります。
MVCCの仕組み
| 概念 | 説明 |
|---|---|
| バージョン(Tuple Version) | 各行が更新されるたびに新しいバージョンが作成され、古いバージョンも一定期間保持される |
| トランザクションID(XID) | 各トランザクションに採番される一意のID。どのバージョンが見えるかを判定するのに使う |
| スナップショット | トランザクション開始時の「どのXIDまでが確定済みか」の記録。これを基に見えるバージョンを決める |
| デッドタプル | 不要になった古いバージョン。VACUUMで回収されるまでディスクに残る |
歴史と背景
- 1981年:P.A. Bernstein・N. Goodmanがマルチバージョン同時実行制御の理論を発表
- 1984年:InterBaseデータベースがMVCCを商用実装した先駆け(後のFirebird)
- 1990年代:OracleがMVCCを採用。「読み取りがロックをブロックしない」ことを差別化ポイントとして訴求
- 1996年:PostgreSQLにMVCCが実装。オープンソースRDBMSへの普及が進む
- 2003年:MySQL 5.0のInnoDBエンジンがMVCCを標準実装。MySQLの同時実行性が大幅改善
- 現在:MVCCはRepeatable Read以上の分離レベルを効率的に実現する標準的アーキテクチャとなっている
主要DBのMVCC実装比較
| DB製品 | MVCC実装 | 不要バージョン回収 |
|---|---|---|
| PostgreSQL | ヒープファイル内にバージョンを蓄積 | VACUUM / autovacuum |
| Oracle | UNDOセグメント(UNDO表領域)に旧値を保存 | 自動(UNDO保持期間設定) |
| MySQL InnoDB | UNDOログにバージョンを保存 | パージスレッドが自動回収 |
| SQL Server | tempdbのバージョンストアに保存 | 自動回収 |
関連する規格・RFC
| 規格 | 内容 |
|---|---|
| ISO/IEC 9075 | スナップショット分離をベースとした分離レベルの実装指針 |
| PostgreSQL MVCC実装 | デッドタプルのVACUUM処理が必須の設計(他DBとは異なる特徴) |
関連用語
- ロック(排他制御) — データの同時更新を防ぐためにアクセスを制限する仕組み
- 分離レベル — 同時実行トランザクション間の干渉の強さを設定するパラメータ
- バキューム・VACUUM — MVCCで蓄積した不要バージョンを回収するPostgreSQLの機能
- トランザクション — 一連のDB操作をひとまとめに扱う仕組み
- ACID特性 — トランザクションが満たすべき4つの性質
- 楽観ロック・悲観ロック — 同時更新を制御する2つのアプローチ
- クエリ最適化・実行計画 — クエリを効率よく実行するためのDBエンジンの最適化処理