トランザクションと排他制御(ロック・デッドロック)
ACID 特性・排他制御・共有ロックと専有ロック・ロックの粒度・デッドロック・2相コミットを、選択肢の言い換えを見て区別できるようになる。共有変数の実行順やロックの両立性を表で1手ずつたどり、待ちやデッドロックが起きるかを判定できるようになる。
用語の区別(ACID 特性・排他制御・デッドロック・2相コミットなど)は本試験でも繰り返し出ます。ロックの両立性や共有変数の実行順をたどる問題は、本試験での出題は少なく、免除試験で多く出ています。どちらも「複数の人が同じデータを同時に触ると何が壊れるか」という同じ話なので、まとめて押さえると効率よく得点できます。
このレッスンで稽古する(用語チェック・過去問)結論:トランザクションは「全部やるか、全部なかったことにするか」の作業単位
トランザクションとは、データベースに対する「ひとまとまりで扱う一連の処理」のことです。たとえば銀行振込は「A の口座から 1 万円引く」と「B の口座に 1 万円足す」の 2 つで 1 セットです。片方だけ実行されてお金が消えたり増えたりするのを防ぐために、DBMS(データベース管理システム)はトランザクション単位で処理を保証します。
- コミット:トランザクションの更新を確定させること
- ロールバック:トランザクションの更新を取り消して、開始前の状態に戻すこと
このレッスンの全体像は次の 3 つです。
- トランザクションが守るべき 4 つの性質=ACID 特性
- 同時に更新しても矛盾しないようにする仕組み=排他制御(ロック)
- ロックの副作用=デッドロックと、複数サーバーで確定をそろえる2相コミット
ACID 特性:4 つの性質を言い換えで見分ける
RDBMS がトランザクションに対して保証する 4 つの性質の頭文字をとって ACID 特性と呼びます。試験では「説明文 → どの性質か」を当てさせる問題が中心です。
| 性質 | 英語 | ひとことで | 選択肢での言い換え |
|---|---|---|---|
| 原子性 | Atomicity | 全部やるか、全部取り消すか | 「全てが実行されるか,全てが取り消されるか」「完全に行うか,全く処理しなかったかのように取り消す」 |
| 一貫性(整合性) | Consistency | データの整合性(ルール)が崩れない | 「整合性が保たれた状態を維持する」 |
| 独立性(隔離性) | Isolation | 同時に動いても互いに影響しない | 「他のトランザクション処理の影響を受けない」 |
| 耐久性 | Durability | 確定した結果は障害後も残る | 「完了後にハードウェア障害が発生しても,内容は保証される」 |
見分けのコツ
- 「全部 or 無」→ 原子性。原子=それ以上分けられない、と覚えます。
- 「他の影響を受けない」→ 独立性。
- 「完了後・障害が起きても残る」→ 耐久性。
- 「何度実行しても結果は同じ」は冪等性(べきとうせい)で、ACID には含まれません。ACID 以外の性質を混ぜてくる選択肢にも注意します。
また、「RDBMS の機能で実現されるトランザクションの性質は?」と聞かれたら答えは ACID 特性です。関数従属性(正規化の話)、候補キーの一意性(表の性質)、データ独立性(スキーマ構造の話)はトランザクションの性質ではありません。
排他制御はなぜ要るのか:同時更新で「更新が消える」
排他制御とは、複数のトランザクションが同じデータを同時に更新しても論理的な矛盾が起きないようにする仕組みです。代表的な方法がロック(作業中のデータに鍵をかけ、他の人に触らせないこと)です。
排他制御をしないと、次のような**更新の消失(ロストアップデート)**が起きます。
| 時刻 | 処理 1 | 処理 2 | カウンタの値 |
|---|---|---|---|
| ① | 100 を読んで +1 → 101 | 100 | |
| ② | 100 を読んで +1 → 101 | 100 | |
| ③ | 101 を書く | 101 | |
| ④ | 101 を書く | 101 |
2 回加算したのに 101 にしかなりません。処理 2 が、処理 1 の書き込み前の古い値を読んでしまったのが原因です。
試験での区別
| 用語 | 目的 |
|---|---|
| 排他制御 | 同時更新による矛盾を防ぐ |
| リカバリ制御 | 障害が起きた後に復旧する |
| アクセス権限・機密保護 | 誰が参照・更新してよいかを決める |
| 正規化 | 表を分けて重複や更新時の不整合をなくす(設計の話) |
| 再編成 | 格納領域を整理し直す(性能・保守の話) |
| 整合性制約 | 主キー・外部キーなどのルールで不正な値を拒否する |
排他制御は「速くするため」でも「デッドロックを防ぐため」でもありません。ロックを使うと、むしろデッドロックの原因になることがあります。
共有ロックと専有ロック:両立するのは「共有×共有」だけ
ロックには 2 種類あります。
- 共有ロック(S ロック):読むときにかける。他の人も読めるが、書き換えはさせない。
- 専有ロック(X ロック・排他ロックとも言う):更新するときにかける。他の人は読むことも書くこともできない。
たとえるなら、美術館の展示品です。共有ロックは「鑑賞中」の状態で、何人でも同時に見られますが、その間は誰も手を加えられません。専有ロックは「修理中」の札で、修理が終わるまでは見ることもできません。
両立性の表(これだけ暗記)
| 先に取られているロック \ 後から要求 | 共有ロック | 専有ロック |
|---|---|---|
| 共有ロック | ○ 取れる | × 待ち |
| 専有ロック | × 待ち | × 待ち |
○ は 4 マスのうち 1 マスだけです。「専有ロック中でも共有ロックなら取れる」は誤りです。
表を使う問題の解き方:先に動いているトランザクションが持つロックと、後から来たトランザクションの要求を資源ごとに 1 つずつ照合します。1 つでも × があれば、後から来た方は待たされます(例題を参照)。
ロックの粒度:大きいほど「待ちが増え」、小さいほど「ロック数とメモリが増える」
ロックの粒度とは、1 回のロックで鍵をかける範囲の大きさです(表全体・ページ・行など)。
| 粒度 | 競合(待ち) | 同時に動ける数(並行性) | ロックの個数・管理メモリ |
|---|---|---|---|
| 大きい(表単位) | 起きやすい | 少ない → スループット低下 | 少ない |
| 小さい(行単位) | 起きにくい | 多い | 多い |
粒度を大きくすると、関係ない行まで巻き込んでロックするため、他のトランザクションの待ちが増えて全体の処理量(スループット)が下がります。一方で、ロックの個数は少なくて済みます。「粒度を大きくすると同時実行数が増える」「ロックの個数が増える」は、関係を逆にしたひっかけです。
デッドロック:お互いが相手の鍵を待って、どちらも進めない
デッドロックとは、複数のトランザクションが互いに相手がロックしている資源を要求して待ち合い、どれも実行できなくなる状態です。単に 1 つが待たされているだけ(専有ロック同士の競合で片方が待つ)ではデッドロックとは言いません。待ちが輪になっているのが条件です。
flowchart LR
A["トランザクション A:X をロック中、Y を待つ"] --> B["トランザクション B:Y をロック中、X を待つ"]
B --> A
- 起きる原因:2 つのトランザクションが同じ資源に逆の順序でロックをかけること。
- 防ぎ方:全トランザクションでロックを取る順序をそろえる。
- 起きたときの対処:DBMS がどれか 1 つのトランザクションをロールバックして輪を断ち切り、後で再実行します。
2相ロック(ロックを取る段階と外す段階を分け、一度外し始めたら新しくロックを取らない方式)を使っても、デッドロックは起こり得ます。2相ロックはデッドロック対策ではありません。
2相コミットと、コミット・ロールバック・ロールフォワードの区別
2相コミットは、分散データベース(データが複数のサイト=サーバーに分かれているもの)で、全サイトの更新をそろえて確定するための方式です。
- 第 1 相:調整役が各サイトに「確定(コミット)できるか」を問い合わせる
- 第 2 相:全サイトが「できる」と答えたらコミット、1 つでも「できない」ならロールバックを指示する
| 用語 | 何をするか |
|---|---|
| 2相コミット | 分散 DB で、全サイトに確定可否を確認してから一斉に確定する |
| 2相ロック | ロックを取る段階と外す段階を分ける排他制御の方式 |
| コミット | 更新を確定する |
| ロールバック | 更新を取り消して開始前に戻す(デッドロック解消・異常終了時) |
| ロールフォワード | 媒体障害のとき、バックアップに更新後のログを順に反映して障害直前まで復元する |
トランザクションの状態遷移:アクティブ → コミット処理中 → コミット済、またはアボート処理中 → アボート済、と進みます。コミット処理中に問題が起きてアボート処理中へ移ることはありますが、アボート処理中からコミット処理中へ戻ることはありません。一度取り消しを始めたら、取り消しを最後までやり切ります。
試験での問われ方
- ACID 特性:説明文から性質名を選ばせます。原子性・独立性・耐久性の説明や、ACID 以外の冪等性が選択肢に並びます。
- 排他制御の目的:「同時更新の矛盾を防ぐ技法は?」と聞かれます。正規化・再編成・リカバリ制御・アクセス権限との区別がポイントです。
- 共有変数の実行順(主に免除試験):手順の並び順を与えて最終値を問います。どの時点の値を読んだかを 1 手ずつ表に書けば、計算ミスなく解けます。
- ロックの両立性:S×S だけ ○ と覚えていれば、文章題も表の問題も解けます。
- 粒度:「大きい → 待ちが増える/ロック数は少ない」の組合せで判定します。
- デッドロック:定義を問う問題と、ロックを取る順序が逆になっていないかを見る問題が出ます。
- 2相コミット:「全サイトに確定可否を問い合わせる」と書いてあれば 2相コミットです。
アクセスカウンタの更新の消失(免除試験)
ア 100
イ 101
ウ 102
エ 104
出典:基本情報技術者試験 科目A免除 修了試験 20250126 実施分 問22
解き方と答えを見る
- 初期値はカウンタ=100。各処理が「いつ何を読んで、何を書いたか」を時刻順に表にする。
- ①:処理ブロック 1 がカウンタを読む → 100。1 を足して 101 を手元に持つ(まだ書いていない)。カウンタは 100 のまま。
- ②:処理ブロック 2 がカウンタを読む → まだ 100。1 を足して 101 を手元に持つ。カウンタは 100 のまま。
- ③:処理ブロック 1 が手元の 101 を書き込む → カウンタ=101。
- ④:処理ブロック 2 が手元の 101 を書き込む → カウンタ=101(①の加算分を上書きして消してしまう)。
- 2 回アクセスしたが、最終値は 100+1=101。102 にならないのは、②が③より前に古い値を読んだため。
答え:イ(101)。排他制御がないと更新の消失が起きる。
共有変数 x を 2 つのタスクが更新する順序(免除試験)
ア a1 → a2 → b1 → b2 → a3 → a4 → b3 → b4
イ a1 → b1 → b2 → b3 → b4 → a2 → a3 → a4
ウ b1 → a1 → a2 → a3 → a4 → b2 → b3 → b4
エ b1 → b2 → b3 → a1 → a2 → a3 → a4 → b4
出典:基本情報技術者試験 科目A免除 修了試験 20221211 実施分 問17
解き方と答えを見る
- 初期値 x=3。タスク A は x=x+x を a1〜a4、タスク B は x=x×x を b1〜b4 で実行する。
- 選択肢イの順序 a1→b1→b2→b3→b4→a2→a3→a4 を 1 手ずつたどる。
- a1:x を読む → e=3。
- b1:x を読む → h=3。b2:x を読む → i=3。
- b3:j=h×i=3×3=9。b4:x=9 に更新。
- a2:x を読む → f=9(B が書いた後の値を読む)。
- a3:g=e+f=3+9=12。a4:x=12 に更新。最終値は 12 で条件に合う。
- 確認としてアの順序もたどる:a1(e=3)→a2(f=3)→b1(h=3)→b2(i=3)→a3(g=6)→a4(x=6)→b3(j=3×3=9)→b4(x=9)。最終値は 9 なので不適。ウ・エも同じようにたどると 12 にならない。
答え:イ。各手順が「その時点の x」を読むことを表で追えば判定できる。
ロック表から資源待ちの有無を判定する
| トランザクション\資源 | A | B | C |
|---|---|---|---|
| 1 | S | − | X |
| 2 | S | X | − |
| 3 | X | S | − |
ア トランザクション 1 の後にトランザクション 3 を開始したとき,トランザクション 3 の資源待ちはない。
イ トランザクション 2 の後にトランザクション 1 を開始したとき,トランザクション 1 の資源待ちはない。
ウ トランザクション 2 の後にトランザクション 3 を開始したとき,トランザクション 3 の資源待ちはない。
エ トランザクション 3 の後にトランザクション 1 を開始したとき,トランザクション 1 の資源待ちはない。
解き方と答えを見る
- 表を整理する:T1=A:S, C:X / T2=A:S, B:X / T3=A:X, B:S(S=共有、X=専有)。
- 判定ルール:先に動いている方が持つロックと後から来た方の要求を資源ごとに照合し、S×S 以外が 1 つでもあれば待ちになる。
- ア(T1 の後に T3):資源 A で T1 が S を持ち、T3 が X を要求 → S×X は × → 待ちあり。
- イ(T2 の後に T1):A は S×S → ○。B は T1 が要求しない。C は T2 が持っていない → ○。待ちなし。
- ウ(T2 の後に T3):A で S×X → × → 待ちあり(B も X×S で ×)。
- エ(T3 の後に T1):A で T3 が X を持ち、T1 が S を要求 → X×S は × → 待ちあり。
答え:イ。待ちが起きないのは、同じ資源で重なるのが共有ロック同士だけの組合せ。
ロックを取る順序からデッドロックの有無を判定する
| ① | ② | ③ | ④ | |
|---|---|---|---|---|
| ア | read W | update Y | update X | update Z |
| イ | read W | update Y | update Z | update X |
| ウ | update X | read W | update Y | update Z |
| エ | update Y | update Z | update X | read W |
ア ①: read W / ②: update Y / ③: update X / ④: update Z
イ ①: read W / ②: update Y / ③: update Z / ④: update X
ウ ①: update X / ②: read W / ③: update Y / ④: update Z
エ ①: update Y / ②: update Z / ③: update X / ④: read W
解き方と答えを見る
- A の順序は read W(S) → update X → update Y → update Z。専有ロックは X→Y→Z の順に取る。
- W はどちらも共有ロックなので S×S で両立し、デッドロックの原因にならない。見るのは X・Y・Z の順序だけ。
- ア:B は Y → X の順。A が X を持って Y を待ち、B が Y を持って X を待つと、待ちが輪になる → デッドロックが起き得る。
- イ:B は Y → Z → X の順。A が X を持って Y を待ち、B が Y・Z を持って X を待つ → デッドロックが起き得る。
- エ:B は Y → Z → X の順(最後に read W)。イと同じ理由でデッドロックが起き得る。
- ウ:B は X → (read W) → Y → Z の順で、A と同じ X→Y→Z の順になる。X を先に取った方が最後まで進み、もう一方は X の手前で待つだけなので、輪にならない。
答え:ウ。全トランザクションでロックを取る順序をそろえれば、デッドロックは起きない。
要点(試験直前に読む)
- ACID:原子性=全部か無か、一貫性=整合性を保つ、独立性=互いに影響しない、耐久性=確定後は障害でも残る。「何度実行しても同じ」は冪等性で ACID 外。
- 排他制御の目的は同時更新による矛盾(更新の消失)を防ぐこと。速くするためでも、デッドロックを防ぐためでもない。
- ロックの両立性は共有×共有だけ ○。専有ロックが絡むと必ず待ちになる。
- 粒度が大きいと待ちが増えてスループットが下がるがロック数は少ない。粒度が小さいとロック数と管理メモリが増える。
- デッドロック=互いに相手のロックを待つ輪。ロックを取る順序をそろえれば防げる。起きたら DBMS がどれかをロールバックする。
- 2相コミット=分散 DB で全サイトに確定可否を聞き、全員 OK なら確定。アボート処理中からコミット処理中には戻らない。
ひっかけ
- 原子性の問題で、耐久性(障害後も残る)・独立性(影響を受けない)・冪等性(何度やっても同じ)の説明を並べてくる。「全部か無か」の言い換えを探せばよい。
- 「専有ロック中でも共有ロックは取れる」「共有ロック中でも専有ロックは取れる」は誤り。S×S 以外はすべて待ちになる。
- 粒度の関係を逆にしてくる(大きくすると同時実行数が増える、ロック数が増える)。「大きい=範囲が広い=巻き込みが多い」と考えれば見破れる。
- 排他制御を「デッドロック防止のため」「アクセス頻度の高いデータを速くするため」と書く選択肢は誤り。排他制御はむしろデッドロックの原因になる。
- デッドロック解消に使うのはロールバック。ロールフォワードは障害復旧、更新の確定はコミット。2相コミットと2相ロックの名前の取り違えにも注意。
用語(18)
データベースに対する一連の処理を、まとめて 1 単位として扱うもの。
トランザクションが満たすべき原子性・一貫性・独立性・耐久性の 4 つの性質。
⚠ 関数従属性(正規化の話)やデータ独立性(スキーマ構造の話)はトランザクションの性質ではない。
トランザクション内の処理は、全部実行されるか全部取り消されるかのどちらかになる性質。
⚠ 「障害後も残る」は耐久性、「他の影響を受けない」は独立性。「全部か無か」なら原子性。
トランザクションの前後で、データの整合性(決められたルール)が保たれる性質。
⚠ 整合性制約(主キーなどのルールそのもの)とは別。一貫性はトランザクションが守る性質の名前。
同時に実行されているトランザクション同士が、互いの処理結果に影響しない性質。
⚠ データ独立性(プログラムとデータ構造を切り離す考え方)と名前が似ているが別物。
コミットした更新結果は、その後に障害が起きても失われない性質。
⚠ 原子性は「途中で止まったら取り消す」話、耐久性は「確定後に残る」話。
トランザクションの更新内容を確定させる操作。
⚠ ロールバックは取り消し。「更新結果を確定するためにロールバック」は誤り。
トランザクションの更新を取り消して、開始前の状態に戻す操作。デッドロックの解消にも使う。
⚠ ロールフォワードは障害後にログを反映して復元すること。取り消し=ロールバック、やり直し=ロールフォワード。
媒体障害のとき、バックアップに更新後のログを順に反映して、障害直前の状態まで復元する操作。
⚠ 異常終了したトランザクションの取り消しやデッドロックの解消はロールバック。
複数のトランザクションが同じデータを同時に更新しても矛盾が起きないよう、アクセスを制御する仕組み。
⚠ リカバリ制御は障害からの復旧。排他制御は性能向上やデッドロック防止が目的ではない。
同時に読んだ古い値から計算した結果で上書きし合い、片方の更新が消えてしまう現象。
読み取り時にかけるロック。他の共有ロックとは両立するが、専有ロックとは両立しない。
⚠ 専有ロックはどのロックとも両立しない。○ になるのは共有×共有だけ。
更新時にかけるロック。かかっている間、他のトランザクションは共有ロックも専有ロックも取れない。
⚠ 「専有ロック中でも共有ロックなら取れる」は誤り。
1 回のロックで鍵をかけるデータの範囲の大きさ(表・ページ・行など)。
⚠ 大きいと待ちが増えて並行性が下がるがロック数は少ない。小さいと待ちは減るがロック数と管理メモリが増える。
複数のトランザクションが互いに相手のロックしている資源を待ち合い、どれも進めなくなる状態。
⚠ 単に 1 つが待たされるだけの競合はデッドロックではない。待ちが輪になっているのが条件。
ロックを取る段階と外す段階を分け、一度外し始めたら新しいロックを取らない排他制御の方式。
⚠ 2相コミットは分散 DB で確定をそろえる方式。2相ロックでもデッドロックは起こり得る。
分散データベースで、全サイトに確定できるかを問い合わせ、全サイトが可能な場合だけ一斉に確定する方式。
⚠ 2相ロック(ロックの取り方)や排他制御と混同させる選択肢が出る。「全サイトに確定可否を問い合わせる」なら 2相コミット。
同じ処理を何度実行しても結果が同じになる性質。
⚠ ACID 特性には含まれない。原子性の選択肢に混ぜて出される。
このレッスンの過去問
- トランザクションのACID特性令和6年度 基本情報技術者試験 科目A 公開問題 問7
- 排他制御の目的(同時更新の矛盾防止)平成28年度 春期 基本情報技術者試験 午前 問30
- 排他制御なし共有変数更新の実行順序トレース基本情報技術者試験 科目A免除 修了試験 20250126 実施分 問22
- 共有ロックと専有ロックの両立性判定平成27年度 秋期 基本情報技術者試験 午前 問29
- ロックの粒度とトランザクション並行性平成30年度 秋期 基本情報技術者試験 午前 問29
- デッドロックの定義令和元年度 秋期 基本情報技術者試験 午前 問29
- 2相コミットの定義(分散DBの更新確認)令和元年度 秋期 基本情報技術者試験 午前 問28