ロストアップデート(更新の喪失)
並行処理の異常の一つ。2つのトランザクションが同じ行を読み、読んだ値をもとにそれぞれ更新すると、後の書き込みが先の書き込みを上書きしてしまう。ロックなしの読み取り→変更→書き込みは、競合すれば確実にバグになる。
典型例はカウンタの加算だ。Tx1がn=5を読んで6を計算し、Tx2もn=5を読んで6を計算する。どちらも6を書き込み、結果はn=6。加算が1回分消えた。対策は4つある。(1) アトミックな演算(UPDATE counter SET n = n + 1)、(2) SELECT ... FOR UPDATEによる行ロック、(3) バージョン列を使い、衝突したら再試行する楽観的並行性制御、(4) SERIALIZABLE分離レベル。PostgreSQLのREPEATABLE READでは、UPDATEが衝突を検知して「could not serialize」でトランザクションを中止する。現代のWebアプリでは、楽観的制御と再試行ループの組み合わせが一般的だ。