- ブラウザURL入力
- DNS名前→IP
- ルータ経路選択
- ロードバランサ振り分け
- Nginx受け口
- アプリ処理
- DB保存今ここ
データベースの内部はこの期で初めて扱います。ここまでの期の「ロック」はCPUやOSの排他制御の話で、これから見るものとは別です。
まず結論
PostgreSQL は `UPDATE` や `DELETE` をしても、古い行をその場で消しません。公式はこの方式を多版同時実行制御の利益を得るために**必要である**と書いています。まだ他のトランザクションから見えている可能性のある行版を、消してはいけないからです。
消さずに残すと、同じ行の複数の版が同時に存在できます。その結果が **reading never blocks writing and writing never blocks reading** という保証です。読む人と書く人が順番待ちをしなくなる——これが出発点になります。
PostgreSQL でテーブルの1行を `UPDATE` したとき、更新前の古い行の内容はどうなるでしょうか。
当てることが目的ではありません。外した予測ほど記憶に残るので、直感で選んでください。
「消さない」が意図された設計であること
データを書き換えたら古い内容は消える。ファイルを上書きした感覚を持ち込むとそう思えます。PostgreSQL はそうなっていません。公式の Routine Vacuuming の節「24.1.2. Recovering Disk Space」はこう始まります。
In PostgreSQL, an
UPDATEorDELETEof a row does not immediately remove the old version of the row. This approach is necessary to gain the benefits of multiversion concurrency control (MVCC, see Chapter 13): the row version must not be deleted while it is still potentially visible to other transactions.
三つに分けて読みます。まず事実——UPDATE も DELETE も古い行版を即座には取り除きません。次に評価——この方式は necessary だと書かれています。実装が追いついていないのでも、後回しにして楽をしているのでもありません。そして理由——コロンの後です。まだ他のトランザクションから見えている可能性がある間は、その行版を削除してはならない。
効いている語は potentially です。「今まさに読まれている最中だから待つ」のではなく、読まれているかもしれない段階で既に消せない扱いになります。
では残すと何が手に入るのか。引用文の中に答えが置かれています。multiversion concurrency control の利益です。以下、その中身を公式の言葉で確かめます。なお本教材が参照するのは PostgreSQL 18 時点の公式ドキュメントです。
PostgreSQL が古い行版をその場で消さない理由を、公式の説明に沿って選んでください。
公式が挙げる利益 — 逐語で読む
Concurrency Control の冒頭は、MVCC を locking と比較する形で説明しています。
The main advantage of using the MVCC model of concurrency control rather than locking is that in MVCC locks acquired for querying (reading) data do not conflict with locks acquired for writing data, and so reading never blocks writing and writing never blocks reading.
長い一文なので構造を取り出します。
比較の相手 locking(ロックによる制御)前提(事実) 読み取り用に取るロックと書き込み用に取るロックが衝突しない← locks acquired for ... do not conflict with ...接続 and so(だから)帰結(結論) reading never blocks writingwriting never blocks reading
よく引用されるのは最後の2行ですが、それは帰結です。前提は「読み用と書き用のロックが衝突しない」という部分にあります。この順序を取り違えると「PostgreSQL はロックを使わない」という別の主張になります。引用文そのものが locks acquired for querying (reading) data と書いています。無いのではなく、ぶつからないという話です。
公式は、この保証がどこまで効くかも書き添えています。
PostgreSQL maintains this guarantee even when providing the strictest level of transaction isolation through the use of an innovative Serializable Snapshot Isolation (SSI) level.
even when に注目します。最も厳しい分離レベルでもこの保証は維持されると読めます。「厳しくすれば何かを失う」という予想は当てにできません。
一方、MVCC が唯一の手段だとも書かれていません。同じページに続きがあります。
Table- and row-level locking facilities are also available in PostgreSQL for applications which don't generally need full transaction isolation and prefer to explicitly manage particular points of conflict.
also available です。衝突点を自分で管理したい場合のために別枠の道具が用意されている、という書き方です。この一文は次回につながります。
MVCC が locking に比べて有利な点として、公式が挙げているものはどれですか。
行を更新する(PostgreSQL)
`UPDATE` は古い行版をその場で消しません。公式は “does not immediately remove the old version of the row” と書き、理由を “the row version must not be deleted while it is still potentially visible to other transactions” とします。読む側から見れば、自分が見ている版は途中で書き換わりません。結果として読む側と書く側が順番待ちをしなくなります。
更新前の版 残る(potentially visible の間は消せない)更新後の版 別に置かれる読む側 自分に見える版を読む → 書き込みを待たない書く側 読み取りの終了を待たない後に残る事 誰からも見えなくなった古い版
厳しい分離レベルでも同じ保証が続く
分離を強くすると保証が弱まる、という予想は成り立ちません。公式は “PostgreSQL maintains this guarantee even when providing the strictest level of transaction isolation through the use of an innovative _Serializable Snapshot Isolation_ (SSI) level.” と書いています。
主語 PostgreSQL動詞 maintains this guarantee条件 even when providing the strictest levelof transaction isolation手段 Serializable Snapshot Isolation (SSI)読み方 「弱い設定のときだけ」ではない
「古い行版を残す」ことと、「最も厳しい分離レベルでも保証が維持される」こと。この2つをつなぐ構造は何でしょうか。
片方は1行に起きること、もう片方は設定全体の話です。しかし「同時に複数の版が存在できる」という同じ土台の上に立っています。
この章のまとめ
UPDATE/DELETEは古い行版を即座に消さない。公式はこれを necessary と書く。- 理由は the row version must not be deleted while it is still potentially visible to other transactions。potentially の間は消せない。
- 得られるのは reading never blocks writing and writing never blocks reading。ただしこれは帰結で、前提は「読み用と書き用のロックが衝突しない」こと。
- 最も厳しい分離レベル(SSI)でも公式は maintains this guarantee even when と書く。強くすると失われる、ではない。
- MVCC だけが手段ではない。Table- and row-level locking facilities are also available。
- 代償は、誰からも見えなくなった古い行版が溜まること。よって掃除の仕組みが必要になる。
自分の現場で確かめる
読んだだけでは身につきません。手元の環境で実際に見てみてください。
理解度チェック
読んだ直後は「分かった」と感じやすいものです。実際に解いて確かめてください。
「MVCC の保証は、分離レベルを一番強くすると失われる」という説明を、公式の記述に照らして評価してください。
用語集(4語)
- MVCC(multiversion concurrency control)
- 公式が locking と対比して説明する同時実行制御の方式。利点は “locks acquired for querying (reading) data do not conflict with locks acquired for writing data” であり、その帰結として “reading never blocks writing and writing never blocks reading” が成り立つ。
- 行版(row version)
- 同じ1行について存在しうる複数の版のこと。公式は消してよい条件を裏側から書いており、“the row version must not be deleted while it is still potentially visible to other transactions” とする。**potentially visible** の間は消せない。
- Serializable Snapshot Isolation(SSI)
- 公式が “an innovative _Serializable Snapshot Isolation_ (SSI) level” と呼ぶ、最も厳しい分離レベルの実現方式。公式はこのレベルを提供するときでも MVCC の保証を維持する(“maintains this guarantee even when”)と書いている。仕組みの詳細は本教材では扱わない。
- テーブル/行レベルのロック
- MVCC とは別枠で提供される機能。公式は “for applications which don't generally need full transaction isolation and prefer to explicitly manage particular points of conflict” という用途を挙げている。衝突点を自分で管理したいときの道具。