MVCCとは
MVCC (Multi-Version Concurrency Control) は、日本語では「多版同時実行制御」と呼ばれます。
- Multi-Version → データの複数バージョンを持つ
- Concurrency Control → 同時実行制御(複数トランザクションが同時に動くときのルール)
MVCCは、データベースでトランザクションごとに「ある時点のデータのスナップショット」を提供し、行の新旧バージョンを使い分けることで、読み取りと書き込みの競合を減らし、高い並行処理性能を実現する技術です。
バージョン管理の必要性
1. 同時アクセスによるデータの一貫性の崩れ
例えば、Aさんがデータを読み取っているときにBさんが同じデータにアクセスして書き換えた場合、Aさんが見ている内容が途中で変わってしまう可能性があります。
このため、「読み取り中はデータを固定」する必要があります。
※この場合の「一貫性」はACIDの**Consistency(一貫性)**とは文脈が異なります。
複数トランザクションが同時に動作している中で、読み取り中のデータが途中で変わってしまい不整合が発生するという意味で使用しており、**Isolation(隔離性)**に近いです。
2. ロックだけではパフォーマンスに影響がある
「読み取り中はロックする」方式だと、他の処理が待たされ、プログラムの実行時間が長くなってしまいます。
特に高負荷なシステムでは致命的です。
3. バージョンを持つことで解決
MVCCでは、新しい更新は新しいバージョンの行として保存し、読み取りは自分のトランザクション開始時点のバージョンを参照します。
例
更新前: v1(在庫=5)
TxA(読取)開始 → v1を見続ける
TxB(更新) → v2(在庫=3)を作る
結果:
TxAが見たのはv1
TxBや新しいTxが見るのはv2
更新時は古い行を直接上書きせず、新しいバージョンを作成します。
トランザクションがコミットされると、その新バージョンが他のトランザクションからも見えるようになります。
もう参照されていない古いバージョンは、データベース内部のクリーンアップ処理(VACUUMやPurgeなど)で削除され、ストレージを無駄にせずに全員が最新版を見られる状態に整理されます。
MVCCのメリットとデメリット
メリット
-
読み取りが基本ロック不要
スナップショットを読むだけなので、読み取りと書き込みが同時に行いやすいです。
また、高負荷環境でもスループットが落ちにくいです。 -
安定した読み取り結果
トランザクション開始時点のデータを最後まで見られます。
途中で他のトランザクションが更新しても、自分の結果は変わりません。 -
同時実行性能の向上
WebサービスやECサイトのように読み取りが多い環境で特に効果的です。
デメリット
-
古いバージョンの管理が必要
データベースごとに古いバージョンの保持方法は異なります。
例: 行に作成/削除TxIDを持つ (PostgreSQL)、Undoログに過去の状態を保存 (MySQL InnoDB)
上記の古いデータを掃除するプロセスが必要です。 -
ストレージの肥大化
長いトランザクションや掃除遅延により古いバージョンが溜まり、ディスク使用量が増えます。
まとめ
MVCCは、読み取りが多いシステムに向いた技術です。
読み取りと書き込みをバージョンで管理することで競合を減らせますが、書き込み同士の競合は防げません。
また、古いバージョンの管理・掃除を適切に行わないと、性能やストレージ使用量に悪影響を与える可能性があります。