【実務・中級編】 MVCC (多版型同時実行制御) – PostgreSQL

「読み込みは書き込みをブロックしない」— PostgreSQLのMVCCが僕たちに教えてくれること

現場でPostgreSQLを触っていると、たまにこんな質問を受けるんだ。「読み取り専用の重い集計クエリを走らせている間、なぜ更新系の処理が止まらないんですか?」ってね。

これ、実はPostgreSQLの心臓部にあるMVCC (Multi-Version Concurrency Control:多版型同時実行制御) という仕組みのおかげなんだ。今回は、この「縁の下の力持ち」がどうやって僕たちのアプリケーションのパフォーマンスを守っているのか、現場目線で紐解いていこう。

—

そもそも、なぜ「ロック」じゃないのか?

MySQLのInnoDBみたいに、行ロックを多用するDBに慣れていると、最初は違和感があるかもしれないね。

もし、読み取りのたびに厳密なロックをかけていたらどうなると思う?
「誰かがデータを読んでいる間、他の人は一切書き込めない」。こんな状態じゃ、今のモダンなWebサービスなんて一瞬でパンクしてしまうよね。

PostgreSQLは「読み取りと書き込みが互いをブロックしない」という設計思想を選んだ。これがMVCCの正体だ。

MVCCの魔法:データは「上書き」されない

MVCCの核心は、「更新しても古いデータは消さない」というルールにあるんだ。

PostgreSQLで`UPDATE`を実行したとき、実際には古いレコードに印をつけて、「これからはこっちの新しいレコードが正解ですよ」という新しい行を物理的に別の場所に書き込んでいるんだ。

これをエンジニア界隈では「タプル(行)のバージョン管理」と呼んでいる。

具体的な挙動を見てみよう

例えば、あるユーザーの残高(`balance`)を更新するトランザクションを考えてみるよ。

1. T1(トランザクションA) が開始される。
2. T1 が行を更新する。このとき、古い行はそのまま残り、新しい行が作成される。
3. T2(トランザクションB) が同じ行を読みに行く。

ここで魔法が起きる。PostgreSQLは、「今のトランザクション(T2)から見て、どのデータが有効か?」を判定するスナップショットという仕組みを使うんだ。

T2は「自分が開始された瞬間に有効だったデータ」だけを見に行くから、T1が裏で何をやろうが、T2は一貫性のある古いデータを読み取り続けられる。だから、読み取りは書き込みを待つ必要がないんだ。

—

実務で意識すべき「バキューム(VACUUM)」の話

ここまで聞くと「最高じゃん!」って思うかもしれないけど、一つだけ落とし穴がある。「不要になった古いデータがゴミとして溜まる」ことだ。

更新を繰り返すと、テーブルの中に「もう誰も参照していない古いバージョンの行」が山のように積み上がる。これが放置されると、ディスク容量を圧迫するし、スキャンする行数が増えてパフォーマンスがガタ落ちする。

ここで登場するのが `VACUUM` だ。

— 実際にはPostgreSQLがバックグラウンドで勝手にやってくれる(Autovacuum)
— けど、大量更新の直後は手動でやることもある
VACUUM ANALYZE users;

Autovacuumがうまく働かないと、いわゆる「テーブルの肥大化(Bloat)」という沼にハマる。現場で「最近クエリが遅いな?」と思ったら、まずはこのMVCCのゴミ掃除が追いついているかを疑うのが、ベテランへの第一歩だよ。

—

実践的なアドバイス

MVCCを理解していると、設計の視点も変わってくるはずだ。

  • 長時間のトランザクションは避ける:

トランザクションをダラダラと開いたままにすると、スナップショットが古いまま固定され、システム全体で古いデータの掃除(VACUUM)ができなくなる。これが「トランザクションIDの周回問題」や「テーブル肥大化」の大きな原因になるんだ。

  • 不要な更新を減らす:

値が変わっていないのに `UPDATE` を発行すると、MVCCの仕組み上、無駄に新しいバージョンが作られてしまう。`WHERE` 句で「実際に値が変わる時だけ更新する」工夫をするだけで、DBの負荷は劇的に軽くなるよ。

まとめ

PostgreSQLのMVCCは、「一貫性を保ちつつ、同時実行性を最大化する」ための、非常にエレガントな仕組みだ。

「読み取りと書き込みが喧嘩しない」というこの特性を深く理解しておけば、パフォーマンスチューニングの引き出しがグッと増えるはずだよ。もし同僚が「DBが重い」と嘆いていたら、まずは「もしかして、MVCCの掃除が間に合ってない?」と声をかけてみてほしい。

さて、今日はここまで。また現場で役立つ深い話をしよう。質問があったら、いつでもSlackに投げてくれよな!

コメント

タイトルとURLをコピーしました