【えむぶいしーしー】

MVCC(多版型同時実行制御) とは?

最終更新:
💡 過去の版を残し、読む人と書く人の待ち合わせを減らす

データの過去の状態を参照できるようにし、読み取りと書き込みの待ち合わせを減らす同時実行制御の仕組み。参照するスナップショットはデータベースや隔離レベルに依存し、更新などではロックも使う。

📌 このページのポイント
過去の版を参照し、待ち合わせを減らす 旧版のスナップショットを読む例 旧版 更新後の版 price 1000 price 1200 参照 更新 読者A 旧版が見える条件 書き手B 1200へ変更 読む版は隔離レベル・SQLで変わる 更新やロック付きの読取ではロックも使う
旧版を参照すべきスナップショットを持つAの例です。参照する時点は隔離レベルなどに依存します。図は論理的な版の関係を示し、物理的な保存方式は省略しています。
ひよこ ひよこ
MVCCって何をする仕組みなの?
ペンギン先生 ペンギン先生
データの過去の状態を残し、読む人と書く人の待ち合わせを減らす仕組みだよ。図書館で本を書き直している間も、別の人が必要な時点のコピーを読めるイメージ。読み取り側に見せる一貫した状態をスナップショットと呼ぶんだ。
ひよこ ひよこ
ロックしなくていいってこと?
ペンギン先生 ペンギン先生
すべてのロックがなくなるわけではないよ。通常の読み取りは、書き込みの完了を待たずに見える版を読める場合がある。一方、同じ行を更新する処理同士や、SELECT FOR UPDATEのようなロック付きの読み取りでは、ロックを使って待つことがあるんだ。
ひよこ ひよこ
読むのは、いつのデータなの?
ペンギン先生 ペンギン先生
データベースと隔離レベルによるよ。PostgreSQLのRead Committedでは、通常のSELECTは各クエリ開始時点でコミット済みのデータを読むので、同じトランザクション内でも次のクエリで結果が変わりうる。Repeatable Readでは、最初のデータ操作時点のスナップショットを使う。どちらも、自分のトランザクションが行った変更は見えるんだ。
ひよこ ひよこ
過去の版はどこに保存しているの?
ペンギン先生 ペンギン先生
実装によって違うよ。PostgreSQLでは更新前の行をテーブル内に残す。MySQLのInnoDBではUndoログの情報から過去の行を復元できるようにする。どちらも過去の状態を参照するための仕組みだけれど、すべてのデータベースが同じ形で行を丸ごと複製するわけではないんだ。
ひよこ ひよこ
古いデータがどんどん増えない?
ペンギン先生 ペンギン先生
不要になった過去の情報はクリーンアップする必要があるよ。PostgreSQLにはVACUUMと、その実行を自動化するautovacuumがあり、InnoDBには不要な履歴を取り除くpurgeがある。長時間のトランザクションが古い版を必要とする間は、その情報を削除できない場合がある。処理時間や履歴の蓄積を見て運用しよう。
ペンギン
まとめ:ざっくりこれだけ覚えればOK!
「MVCC」って出てきたら「データの過去の状態を参照できるようにして、読み書きの待ち合わせを減らす仕組み」と思えばだいたいOK!
📖 おまけ:英語の意味
「Multi-Version Concurrency Control」 = 多版型同時実行制御
💬 Multiple Versions(複数バージョン)で Concurrency(同時実行)を Control(制御)するという意味だよ

参考資料

← 用語集にもどる