コンテンツにスキップ

同時実行制御(排他制御)

データベースでは、複数の処理をひとまとまりとして扱う単位をトランザクションと呼びます。「ひとまとまり」とは、途中で分割できない一連の処理のことです。

身近な例で考えてみましょう。銀行の口座振替では、次の2つの処理が必ずセットで行われます。

  1. Aさんの口座から10,000円を引く
  2. Bさんの口座に10,000円を加える

もし処理1だけが実行されて処理2が失敗したら、Aさんのお金が消えてしまいます。このような事態を防ぐために、この2つの処理を1つのトランザクションとして扱い、「両方成功するか、両方取り消すか」のどちらかにします。

現実のデータベースでは、複数の利用者やプログラムが同時にデータにアクセスします。このとき、何の制御もなければデータの不整合が発生します。

具体的なシナリオを見てみましょう。ある商品の在庫数が「10個」のとき、2台のPCから同時に注文処理が行われた場合を考えます。

  1. PC-Aが在庫数「10」を読み取る
  2. PC-Bも在庫数「10」を読み取る
  3. PC-Aが「10 − 3 = 7」と計算して在庫を「7」に更新する
  4. PC-Bが「10 − 2 = 8」と計算して在庫を「8」に更新する

本来、在庫は「10 − 3 − 2 = 5」になるべきですが、PC-Bの更新がPC-Aの更新を上書きしてしまい、在庫が「8」になってしまいます。このように後からの書き込みが先の更新を上書きしてしまう問題は、排他制御がないと起こる典型的なトラブルです。

このような問題を防ぐために、複数の利用者が同時にデータにアクセスしたときにデータの整合性を保つ仕組みが同時実行制御排他制御)です。

試験で出るポイント

排他制御の目的は「データの整合性を保つこと」です。「改ざんを防ぐ」「アクセス権を管理する」といった選択肢はセキュリティの話であり、排他制御とは目的が異なります。引っかけ選択肢として頻出なので注意しましょう。

排他制御の基本的な仕組みは、データにロック(鍵)をかけることです。あるトランザクションがデータを使用している間はロックをかけ、他のトランザクションがそのデータにアクセスできないようにします。先ほどの在庫の例でロックを使うと、次のようになります。

  1. PC-Aが在庫データにロックをかけ、「10」を読み取る
  2. PC-Bが在庫データにアクセスしようとするが、ロックがかかっているため待ち状態になる
  3. PC-Aが「10 − 3 = 7」に更新し、ロックを解除する
  4. PC-Bがロックをかけ、「7」を読み取る
  5. PC-Bが「7 − 2 = 5」に更新し、ロックを解除する

このように、ロックによって処理を順番に行わせることで、正しい結果(在庫「5」)が得られます。

sequenceDiagram
    participant A as PC-A
    participant DB as 在庫データ
    participant B as PC-B

    A->>DB: ①ロック&読み取り(10)
    B--xDB: ②アクセス要求(ロック中で待ち)
    Note right of B: 待ち状態
    A->>DB: ③更新(10→7)&ロック解除
    B->>DB: ④ロック&読み取り(7)
    B->>DB: ⑤更新(7→5)&ロック解除
    Note over DB: 在庫:5個(正しい結果)

  classDef base fill:#f8fafc,stroke:#94a3b8,stroke-width:1px,color:#333;
  classDef primary fill:#eff6ff,stroke:#2563eb,stroke-width:2px,color:#1e40af;
  classDef alert fill:#fef2f2,stroke:#dc2626,stroke-width:2px,color:#991b1b;

トランザクションが信頼できる処理であるために満たすべき4つの性質をACID特性と呼びます。ACIDとは、4つの性質の英語の頭文字を取ったものです。

特性英語意味具体例(口座振替)
原子性Atomicityトランザクションの処理は「すべて実行される」か「まったく実行されない」かのどちらかになる引き出しと入金が両方成功するか、両方取り消されるか
一貫性Consistencyトランザクションの前後でデータベースの整合性が保たれる振替の前後で、2つの口座の合計金額は変わらない
独立性Isolation同時に実行される複数のトランザクションが互いに干渉しないAさんとCさんが同時に振込しても、結果が正しく反映される
永続性Durability完了したトランザクションの結果は、障害が起きても失われない振替完了後にサーバーが故障しても、記録は残っている

4つの特性はそれぞれ異なる側面からデータの信頼性を支えています。「原子性」は処理の完全性、「一貫性」はデータの正しさ、「独立性」は並行処理の安全性、「永続性」は結果の保存を保証します。

試験で出るポイント

ACID特性のなかでも**原子性(Atomicity)**は最も出題されやすい特性です。「トランザクションの処理がすべて実行されるか、まったく実行されないかのどちらかであること」という説明が選択肢に出たら、原子性を選びましょう。

排他制御にはロックが不可欠ですが、ロックの使い方によってはデッドロックという問題が発生することがあります。デッドロックとは、2つ以上のトランザクションが互いに相手のロック解除を待ち続け、どちらも先に進めなくなる状態のことです。

たとえば、次のような状況を考えます。

  1. トランザクションAが「データX」にロックをかける
  2. トランザクションBが「データY」にロックをかける
  3. トランザクションAが「データY」を使いたいが、Bがロック中なので待つ
  4. トランザクションBが「データX」を使いたいが、Aがロック中なので待つ

こうなると、AはBを待ち、BはAを待つという永遠の待ち合い状態になります。これがデッドロックです。

デッドロックが発生した場合、データベース管理システム(DBMS)がこれを検出し、一方のトランザクションを強制的に取り消す(ロールバックする)ことで解消します。

graph TB
    A["トランザクションA"]:::primary
    B["トランザクションB"]:::primary
    X["データX"]:::base
    Y["データY"]:::base
    DL["デッドロック発生!"]:::alert

    A -- "ロック中" --> X
    B -- "ロック中" --> Y
    A -. "待ち" .-> Y
    B -. "待ち" .-> X

    X ~~~ DL ~~~ Y

  classDef base fill:#f8fafc,stroke:#94a3b8,stroke-width:1px,color:#333;
  classDef primary fill:#eff6ff,stroke:#2563eb,stroke-width:2px,color:#1e40af;
  classDef alert fill:#fef2f2,stroke:#dc2626,stroke-width:2px,color:#991b1b;

試験で出るポイント

デッドロックは「2つのトランザクションが互いにロックを待ち合って動けなくなる状態」です。単に「処理が遅い」状態とは異なり、介入がなければ永遠に解消しない点がポイントです。

ここまでの話は1台のデータベースの中での制御でしたが、実際のシステムでは複数のデータベースにまたがって処理を行うことがあります。たとえば、東京のデータベースと大阪のデータベースの両方を更新する必要がある場合です。

このような分散データベース環境で、すべてのデータベースの処理を確実に成功させる(または全部取り消す)ための仕組みが2相コミットメント(2フェーズコミット)です。名前のとおり、処理を2つの段階(フェーズ)に分けて実行します。

フェーズ名称内容
第1相準備フェーズ調整役が各データベースに「コミット(確定)してよいか?」と問い合わせる。各データベースは「OK」または「NG」を回答する
第2相コミットフェーズ全員が「OK」なら全データベースにコミットを指示する。1つでも「NG」があれば全データベースにロールバック(取り消し)を指示する

この2段階の手順により、分散環境でもトランザクションの原子性(全部成功か全部取り消しか)が保たれます。

試験で出るポイント

2相コミットメントは「分散データベースで整合性を保つ仕組み」であること、そして「全員OKならコミット、1つでもNGなら全体をロールバック」という動きを押さえておけば十分です。

まとめ ── 同時実行制御の全体像

Section titled “まとめ ── 同時実行制御の全体像”
用語ひとことまとめ
トランザクション分割できない一連の処理のまとまり
排他制御(ロック)データにロックをかけて同時アクセスの不整合を防ぐ仕組み
ACID特性トランザクションが満たすべき4つの性質(原子性・一貫性・独立性・永続性)
デッドロック複数のトランザクションが互いにロック解除を待ち合い、動けなくなる状態
2相コミットメント分散データベースで全体の整合性を保つための2段階の確定手順

試験で出るポイント

この分野では「排他制御の目的=データの整合性確保」「ACID特性の原子性=全か無か」「デッドロック=互いにロック待ち」の3つが特に問われます。それぞれの用語を「何のために」「どういう仕組みか」で理解しておきましょう。


過去問に挑戦

Q. トランザクション処理のACID特性に関する記述として,適切なものはどれか。

  • ア 索引を用意することによって,データの検索時の検索速度を高めることができる。
  • イ データの更新時に,一連の処理が全て実行されるか,全く実行されないように制御することによって,原子性を保証することができる。
  • ウ データベースの複製を複数のサーバに分散配置することによって,可用性を高めることができる。
  • エ テーブルを正規化することによって,データに矛盾や重複が生じるのを防ぐことができる。
解答(令和4年)

正解: イ

もっと過去問を解きたい方へ

フライトパスアプリなら、詳しい解説や分野別の過去問演習、SRS(間隔反復)学習ができます。

アプリで効率的に学習しよう