問題 15★★★

在庫数が10の商品に、二つの注文処理がほぼ同時に行われた。どちらの処理も 在庫数10を読み出し、1を引いた9を書き込んだため、8になるべき在庫数が9になった。 この不具合を防ぐ仕組みとして、最も適切なものはどれか。

正解:エ

各選択肢の解説

  1. ア在庫数を複数の表に重複して持たないよう表を分け、1か所だけを更新する。

    誤り。正規化の考え方です。同じ値を何か所にも持つと、一部だけ直して 食い違う不具合が起きるため、それを防ぎます。今回は在庫数が1か所しかなくても 起きる、同時に更新したことによる上書きなので、正規化では防げません。

  2. イ処理が途中で失敗したときに、その処理の更新を取り消して開始前に戻す。

    誤り。ロールバックの説明です。「失敗したら元に戻す」仕組みなので、 今回のように両方の処理が最後まで成功してしまった場合には働きません。 失敗への備えか、同時に動くことへの備えかで区別します。

  3. ウ更新を終えた処理から順に、その処理の変更をデータベースに確定させる。

    誤り。コミットの説明です。二つの処理がそれぞれ9を書き込んで順に確定させても、 結果は9のままです。コミットは変更を確定させる操作で、処理どうしが 同じデータを奪い合うのを調整する仕組みではありません。

  4. エ一方が在庫数を読み出してから更新を終えるまで、他方にその在庫数を扱わせない。

    正解。排他制御(ロック)です。後の処理は先の処理が終わるまで待たされ、 9になった在庫数を読み出してから1を引くので、正しく8になります。

理解を深めるために

同じデータを同時に書き換えさせない

一つしかない共有のノートを、二人が同時に書き直そうとする場面を考えます。 二人とも同じページを見て計算し、あとから書いた人が前の人の書き込みを 上書きしてしまえば、先に書いた分は消えてしまいます。 一人が書き終えるまで、もう一人にはノートを渡さない。これが排他制御です。

なぜ在庫数が9になったのか

問題の場面を順に並べると、次のようになります。

  • 処理Xが在庫数10を読み出す
  • 処理Yも在庫数10を読み出す(Xの結果をまだ知らない)
  • Xが9を書き込む
  • Yも9を書き込み、Xの更新が上書きされて消える

これを更新の消失と呼びます。排他制御(同時実行制御)では、Xが読み出した時点で 在庫数にロックを掛け、Xが更新を終えるまでYを待たせます。YはXの結果である9を 読み出してから1を引くので、在庫数は正しく8になります。

どちらの処理も失敗していないので、失敗に備える仕組みでは防げない点が この問題の要点です。なお、ロックで待たせる向きが互いを指すと、 デッドロックという別の問題が起こることもあります。

混同しやすい仕組みとの違い

仕組み 何を防ぐ・何をするか
排他制御(ロック) 同時に動く処理が同じデータを上書きし合うのを防ぐ
ロールバック 失敗した処理の更新を取り消し、開始前に戻す
コミット 成功した処理の更新を確定させる
正規化 同じ値を複数の場所に持つことで起きる食い違いを防ぐ

試験では「同時に」「複数の利用者が同じデータを」という言い回しが排他制御の合図です。 「途中で障害が起きた」ならロールバック、と条件で読み分けると迷いません。

前の問題へ次の問題へ