データベース操作・制御

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で回収されるまでディスクに残る
MVCCの動作イメージ トランザクションA(読み取り / XID=100で開始) → スナップショット:XID<100 の確定済みデータが見える トランザクションB(書き込み / XID=101) → 行を更新:旧バージョン(XID=99で作成)に加え新バージョン(XID=101)を追記 旧バージョン(XID=99) Aのスナップショットに含まれる→見える 新バージョン(XID=101) AのスナップショットはXID<100→見えない BがCOMMITしても、Aは自分のスナップショット内の旧バージョンを参照し続ける

歴史と背景

  • 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
OracleUNDOセグメント(UNDO表領域)に旧値を保存自動(UNDO保持期間設定)
MySQL InnoDBUNDOログにバージョンを保存パージスレッドが自動回収
SQL Servertempdbのバージョンストアに保存自動回収

関連する規格・RFC

規格内容
ISO/IEC 9075スナップショット分離をベースとした分離レベルの実装指針
PostgreSQL MVCC実装デッドタプルのVACUUM処理が必須の設計(他DBとは異なる特徴)

関連用語