データベースの基礎
在庫表のある商品の在庫数は10である。トランザクションT1は在庫数を読み出して3を引いた値を書き込み、T2は在庫数を読み出して5を引いた値を書き込む。ロックをかけずに、T1の読み出し、T2の読み出し、T1の書き込み、T2の書き込みの順に実行されたとき、最終的な在庫数はいくつになるか。
- A2
- B5
- C7
答えと解説を見る
正解:B. 5
T1とT2はどちらも、相手が書き込む前の在庫数10を読み出します。T1は 10 − 3 = 7 を書き込みますが、そのあとT2が、自分が読み出した10をもとに計算した 10 − 5 = 5 で上書きするので、最終的な在庫数は5になります。本来は2つの処理を順番に行った 10 − 3 − 5 = 2 になるべきで、T1の更新が失われています。これを更新の消失(ロストアップデート)と呼びます。防ぐには、読み出すときに専有ロック(排他ロック)をかけて、T1が終わるまでT2の読み出しを待たせる(SELECT … FOR UPDATE など)か、UPDATE 在庫 SET 在庫数 = 在庫数 - 3 のように、読み出しと書き込みを1つのSQL文で行います。
- A. 2つの処理を順番に実行した場合の正しい値ですが、この順序ではT1の更新が失われます。
- B. 正しい。T2が古い値10をもとに計算した5で上書きし、T1の更新が失われます。
- C. T1が書き込んだ値です。そのあとT2が上書きします。