データベース
下の動画はこの節の解説ではありません。 解説動画の雰囲気を知っていただくための見本として、「AI・機械学習」の動画を再生します。
この節の解説動画はプレミアム限定です。プレミアムなら全科目・全節が見放題!
プレミアムで見る銀行の振込で、引き落としだけが行われて入金が行われなかったら——お金が消えてしまいます。複数の更新処理を「途中で止まらないひとかたまり」として扱う仕組みが、トランザクションです。この節では、トランザクションという処理の単位と、それが満たすべき4つの性質(ACID特性)を押さえます。さらに、複数の利用者が同じデータを同時に触ったときに何が起きるのか、それをどう防ぐのか(ロック方式)、防ごうとして起きる新たな問題(デッドロック)までを順に見ていきます。ACID特性は令和2年度に、それぞれの性質の説明を入れ替える形で出題されました。
簡単にいうと
振込って、実は2つの処理でできているの。引き落としと入金。この2つは「どっちもやるか、どっちもやらないか」でなければ困る。その「ひとかたまり」がトランザクションだよ!
① データベース制御とトランザクション
データベース制御には、データの整合性を確保する同時実行制御機能や障害回復を行う機能などが含まれます。これらの機能は、データベースにおけるトランザクションという単位で制御が行われます。
② トランザクションとは
トランザクションとは、データを操作する際の処理の単位(分けることができない単位)です。
「分けることができない単位」という表現が本質です。物理でいう原子(atom)のように、それ以上分割してはいけないひとかたまりを指します。
③ トランザクション管理
ある操作において、複数の更新処理がある場合、中途半端なところで処理が終了しデータ矛盾などが発生しないように管理することを、トランザクション管理といいます。
振込処理の例
たとえば振込処理の場合、ある口座から引落した金額を振込先に加算する処理を1つのトランザクションとして処理するということです。両方の処理が完了しないとデータに矛盾が生じるからです。
家賃10万円を振り込む場面を、細かく分解してみます。
| 順番 |
|---|
具体例
在庫引き当てで考える——トランザクションの範囲
ECサイトで注文が入ったときの処理を考えます。
処理の一覧
| 番号 | 処理 |
|---|---|
| ① | 在庫数を確認する |
| ② | 在庫数を減らす |
| ③ | 注文データを登録する |
| ④ | 決済を実行する |
| ⑤ | 注文確認メールを送る |
| ⑥ | 倉庫システムに出荷指示を送る |

トランザクションとトランザクション管理
試験のポイント
簡単にいうと
トランザクションが守るべき4つの約束、その頭文字を並べるとACID。名前が似ていて混ざりやすいから、「何を保証しているか」を1語で言えるようにしておこう!
① ACID特性とは
トランザクションは、次の4つの性質(ACID特性)を満たすことが求められます。4つの頭文字をつなげてACIDです。
② Atomicity(原子性)
トランザクションを構成する処理が不可分であること。つまり、トランザクションは「完全に実行されるか」「まったく実行されないか」のいずれかの状態で終了します。
同じ内容を言い換えた表現も押さえておきましょう。
前のテーマの振込の例でいえば、「引き落としだけ完了した状態」は存在してはならない、ということです。
簡単にいうと
2人が同時に在庫を見て、同時に減らしたら、片方の分が消えてしまう。これを防ぐのがロック!「いま使ってるから触らないで」という札を立てるんだ。
① 同時実行制御機能
処理が込み入っていたり、使う人が大勢いたりすると、同じデータに複数のトランザクションが同時に手を伸ばす場面が出てきます。
その際、トランザクション同士が互いに干渉せず、単独で実行されたかのように制御することを同時実行制御といいます。これはACID特性の独立性(Isolation)を実現する仕組みにほかなりません。
同時実行制御は、DBMSの機能などを利用して設定します。同時実行制御を実現する代表的な方法に、ロック方式があります。
② 同時実行制御がないと何が起きるか
商品Aの在庫が100個あり、2人が同時に処理を始めた場面を考えます。
簡単にいうと
お互いに「そっち先に譲って」と言い合って、誰も動けない状態——それがデッドロック!狭い廊下で2人がすれ違えなくなるのと同じ。防ぐには「順番を決めておく」のが一番なんだ。
① デッドロックとは
ロック方式は、処理対象のデータにロックをかけ、他のトランザクションを排他するシンプルな方式ですが、デッドロックが発生するという問題点があります。
デッドロックとは、ロック対象のデータが複数にわたる場合、各トランザクションが相互に必要なデータをロックし合い、互いにロックが解除されるのを待つ膠着状態のことです。
② どうやって起きるのか
2つのトランザクションが、2つのデータベース(または表)を使う場面を考えます。
| トランザクションA | トランザクションB |
|---|
動画・テキスト・過去問・AI添削まですべて網羅!
予備校代の1/10以下で、独学の不安をまるごと解決できます
| ① | 借主の口座の残高を参照する |
| ② | 借主の口座の残高から家賃10万円を減らす |
| ③ | 貸主の口座の残高を参照する |
| ④ | 貸主の口座の残高に家賃10万円を加える |
①から④までがトランザクションの単位(処理の単位)です。
④ 途中で止まると何が起きるか
②が終わった直後にシステムが停止したとします。
| 状態 | 借主の口座 | 貸主の口座 | 世の中のお金 |
|---|---|---|---|
| 処理前 | 50万円 | 100万円 | 150万円 |
| ②の直後で停止 | 40万円 | 100万円 | 140万円 |
| ④まで完了 | 40万円 | 110万円 | 150万円 |
②の直後で止まると、10万円がどこにも存在しないことになります。これがデータ矛盾です。
だからこそ、①〜④を「途中で止まることのないひとかたまり」として扱う必要があります。トランザクションとは、業務上の意味でひとまとまりの処理であり、システムの都合で決まるものではありません。
⑤ コミットとロールバック
トランザクションの終わり方には2通りあります。
| 用語 | 意味 |
|---|---|
| コミット | トランザクションが正常に完了し、更新内容をデータベースに確定させること |
| ロールバック | トランザクションを取り消し、開始前の状態に戻すこと |
「途中で止まらない」という性質は、実際には「途中で問題が起きたら、始める前の状態に戻す」ことで実現されています。ロールバックの詳細は次節で学びます。
⑥ どこまでを1つのトランザクションにするか
これは設計上の判断であり、業務の意味から決まります。
| 業務 | 1つのトランザクションに含めるべき処理 |
|---|---|
| 銀行振込 | 引き落としと入金 |
| 商品の受注 | 受注登録と在庫の引き当て |
| 売上の計上 | 売上明細の登録と売掛金の計上 |
| 会員の退会 | 会員情報の状態変更と、関連する予約の取り消し |
いずれも「片方だけ行われたら困る」処理の組み合わせです。逆に、「商品を注文する」と「注文確認メールを送る」は、メールが届かなくても注文そのものは成立するので、別のトランザクションにすることもあります。
業務の観点から「一蓮托生であるべき処理は何か」を考える——これがトランザクション設計の出発点です。
どこまでを1つのトランザクションにするか
| 範囲 | 判断 |
|---|---|
| ①②③ | 1つのトランザクションにすべき。在庫だけ減って注文が登録されない、注文だけ登録されて在庫が減らない、のどちらも許されない |
| ④ | 別システム(決済代行)との連携なので、同じトランザクションに含めにくい。失敗したら②③を取り消す仕組みが要る |
| ⑤ | メールの送信失敗で注文を取り消す必要はない。別扱いでよい |
| ⑥ | 倉庫システムが一時的に止まっていても、注文は成立させたい。別扱いでよい |
①②③を分けたらどうなるか
②と③を別のトランザクションにすると、②の直後にシステムが停止した場合、
という状態になります。誰も注文していない商品の在庫が減ったままになり、実在庫と帳簿在庫が食い違います。
これは第2章で学んだ「表計算ソフトで在庫を管理すると数字が合わなくなる」現象の、根本的な原因でもあります。表計算ソフトにはトランザクションという概念がないため、複数の処理をひとかたまりとして保証できないのです。
確認してみましょう
> 次の記述の正誤を判定せよ。
> a トランザクションとは、データを操作する際の処理の単位であり、分けることができない単位である。
> b トランザクション管理とは、複数の更新処理がある場合に、中途半端なところで処理が終了しデータ矛盾が発生しないように管理することである。
> c 振込処理では、引き落としと入金をそれぞれ別のトランザクションとして処理するのが原則である。
解答 a:○ b:○ c:×
③ Consistency(一貫性、整合性)
トランザクションによる実行結果(終了状態)にかかわらず、データベースの整合性が保たれている(矛盾のない状態である)こと。
トランザクションが成功しても失敗しても、終わったあとのデータベースは必ず矛盾のない状態になっている、という保証です。たとえば「在庫数は0以上でなければならない」という決まりがあるなら、どんな処理の結果であっても在庫数が負にはならない、ということです。
④ Isolation(独立性)
トランザクションは他のトランザクションの実行による影響を受けないこと。
複数の処理が同時に走っていても、それぞれが自分ひとりで動いているかのように振る舞う、という保証です。次のテーマで学ぶ同時実行制御が、この性質を実現しています。
⑤ Durability(持続性、耐久性)
トランザクションの結果は、障害が発生しても失われてはいけないこと。
いったん「完了した」と応答した以上、そのあとに停電が起きても、その内容は残っていなければならない、ということです。次節で学ぶログ管理とロールフォワードが、この性質を支えています。
⑥ 4つを1枚の表で
| 名称 | 日本語 | 保証すること | ひとことで |
|---|---|---|---|
| Atomicity | 原子性 | 完全に実行されるか、まったく実行されないか | 全部か、ゼロか |
| Consistency | 一貫性、整合性 | 終了状態にかかわらず矛盾のない状態 | 矛盾しない |
| Isolation | 独立性 | 他のトランザクションの影響を受けない | 邪魔されない |
| Durability | 持続性、耐久性 | 障害が発生しても結果が失われない | 消えない |
⑦ 取り違えを防ぐ
試験では、4つの説明を入れ替える形で出題されます。とくに混同しやすいのは次の2組です。
| 混同しやすい組 | 見分ける決め手 |
|---|---|
| 原子性と一貫性 | 原子性は実行の途中がないこと、一貫性は終わったあとが矛盾しないこと |
| 独立性と一貫性 | 独立性は他のトランザクションとの関係、一貫性はデータそのものの状態 |
そしてもうひとつ、「障害からの復旧」と結びつくのは持続性(Durability)です。「異常発生前の状態にまで復旧できることを保証する」という記述が出てきたら、それは独立性ではなく持続性の話です。
⑧ キーワードで結びつける
| 選択肢に出てくる語 | 対応する特性 |
|---|---|
| 「すべて正常に終了したときだけ反映」「処理済か未処理か」 | 原子性 |
| 「矛盾のない状態」「何度実行しても同じ結果」 | 一貫性 |
| 「逐次的に実行する場合と同時に実行する場合で結果が同じ」「他の影響を受けない」 | 独立性 |
| 「障害が発生しても失われない」「復旧できることを保証」 | 持続性 |
このキーワード表を頭に入れておけば、設問の文章を読んだ瞬間に対応する特性が浮かびます。
具体例
設例 ACID特性
> 次の記述の正誤を判定せよ。(令和2年度第7問 改題)
> ア システムに異常が発生したときに、ログなどを用いて異常発生前の状態にまで復旧できることを保証しなければならない。このような特性を「独立性(Isolation)」という。
> ウ トランザクションを構成する全ての処理が正常に終了したときだけ、処理結果をデータベースに反映する必要がある。このような特性を「原子性(Atomicity)」という。
> エ 複数のトランザクションを処理する際には、各トランザクションを逐次的に実行する場合と同時に実行する場合で、処理結果が同じである必要がある。このような特性を「一貫性(Consistency)」という。
解答 ア:× ウ:○ エ:×
アとエの誤りの構造
どちらも正しい説明文に、別の特性の名前を貼り付けた形です。説明文そのものは正しいので、読んでいて違和感がありません。
| 選択肢 | 説明文が指すもの | 貼られた名前 |
|---|---|---|
| ア | 持続性 | 独立性 |
| エ | 独立性 | 一貫性 |
対策は「説明文を読んだら、名前を見る前に自分で答えを出す」
「ログを使って異常発生前の状態に復旧できる……これは持続性だな」と自分の答えを決めてから、選択肢の名前を見る。一致しなければ×。この順番で読めば、貼り付けられた名前に引きずられません。
4つの特性を、振込の場面で総ざらい
家賃10万円の振込を例に、4つの特性が何を守っているかを確かめます。
| 特性 | この場面で守っていること |
|---|---|
| 原子性 | 引き落としだけ、入金だけ、という状態を作らない |
| 一貫性 | 処理の前後で、2つの口座の合計金額が変わらない |
| 独立性 | 同じ口座に対して別の振込が同時に走っても、互いに干渉しない |
| 持続性 | 「振込完了」と表示された後で停電しても、入金は残っている |
もし1つでも欠けたら
| 欠けた特性 | 起きること |
|---|---|
| 原子性がない | お金が消える、または増える |
| 一貫性がない | 残高がマイナスになる |
| 独立性がない | 同時の2件の振込で、片方の金額が上書きされる |
| 持続性がない | 完了したはずの振込が、停電後になかったことになる |
どれも「銀行として成り立たない」
だからこそ、金融システムのような業務では、ACID特性を厳密に保証するリレーショナルデータベースが選ばれます。第1節で見た「NoSQLは速度と柔軟性を優先するかわりに、この保証を緩めている」という話が、ここでつながります。
確認してみましょう
> 次の記述と対応する特性を答えよ。
> a トランザクションを複数同時に実行しても、単独実行の場合と同じ処理結果になる。
> b トランザクション完了後、ハードウェア障害が発生しても更新内容は保証される。
> c 処理の一部が行われている状態は存在しない。
解答 a:独立性(Isolation) b:持続性/耐久性(Durability) c:原子性(Atomicity)

トランザクションとACID特性
試験のポイント
| 順番 | ユーザ甲 | ユーザ乙 | データベースの値 |
|---|
| (1) | 在庫数を表示 → 100 | 100 | |
| (2) | 在庫数を表示 → 100 | 100 | |
| (3) | 在庫から−20 → | 80 | |
| (4) | 在庫から−30 → | 70 |
商品Aの在庫数は、20個と30個が出たので になっていなければいけないのに、70になってしまいました。
原因は(2)にあります。乙が在庫数を読んだ時点では、甲がまだ更新していないため100が返ります。乙はその100をもとに計算するので、甲の更新(−20)がなかったことになってしまうのです。これを更新の喪失(ロストアップデート)といいます。
③ ロック方式(排他制御)
トランザクション実行時に処理対象のデータにロックをかけ、他のトランザクションがアクセスできないよう制御する方式です。
最初にロックをかけたトランザクションが終了した後、次のトランザクションが実行可能となります。この方法を排他制御とよぶこともあります。
先ほどの例に当てはめると
処理(1)で商品Aの在庫データをロックし、処理(3)が完了するまで他のトランザクションで使用できなくします。
| 順番 | ユーザ甲 | ユーザ乙 | データベースの値 |
|---|---|---|---|
| (1) | 在庫数を表示 → 100(ロック) | 100 | |
| (2) | 待たされる | 100 | |
| (3) | 在庫から−20 → 80(ロック解除) | 80 | |
| (4) | 在庫数を表示 → 80 | 80 | |
| (5) | 在庫から−30 → | 50 |
正しく50になりました。乙を待たせることで、甲の更新結果を見てから計算させる——これがロック方式の働きです。
④ ロックの2種類
ロックには、共有ロックと占有ロックの2種類があります。
| 名称 | 利用する場面 | 他トランザクションに対する許可 | ||||
|---|---|---|---|---|---|---|
| 参照 | 更新 | 削除 | 共有ロック | 占有ロック | ||
| 共有ロック | データの参照時 | ○ | × | × | ○ | × |
| 占有ロック | データの更新時および削除時 | × | × | × | × | × |
(○:許可 ×:禁止)
※トランザクションAがあるデータを共有ロックしている場合、トランザクションBは同一データに対して共有ロックをかけることができます。
⑤ 2種類の使い分けを理解する
なぜ2種類あるのでしょうか。読むだけなら何人同時でも困らないからです。
| 場面 | 問題が起きるか |
|---|---|
| 甲が読む、乙も読む | 問題なし。読むだけなら値は変わらない |
| 甲が読む、乙が書く | 問題あり。甲が読んだ値が古くなる |
| 甲が書く、乙も書く | 問題あり。更新の喪失が起きる |
「読む」どうしだけは共存できるので、参照時には共有ロックをかけて、他の参照は許すという設計になっています。全部を占有ロックにしてしまうと、単に一覧を見たいだけの利用者まで延々と待たされることになります。
共有ロック=「読んでもいいが、書くな」、占有ロック=「読むことも書くことも許さない」——この理解で表の中身は再現できます。
⑥ 名前の由来
名前がそのまま「他人と分け合えるか、独り占めか」を表しています。排他ロックとよばれることもあります。
具体例
ロックの粒度という考え方
ロックをかける範囲のことをロックの粒度といいます。
| 粒度 | 範囲 | 同時実行性 | 管理の手間 |
|---|---|---|---|
| 粗い | テーブル全体 | 低い(待ちが増える) | 小さい |
| 細かい | 1行ずつのレコード単位 | 高い(待ちが減る) | 大きい |
極端な例で考える
テーブル全体をロックする場合……商品Aの在庫を更新している間、商品Bの在庫を見ることすらできません。1人が処理している間、他の全員が待たされます。安全ですが、実用に耐えません。
1行ずつロックする場合……商品Aを更新していても、商品Bには影響しません。同時に多くの処理を捌けます。ただし、DBMSは「いまどの行がロックされているか」を大量に管理することになり、その負荷がかかります。
実務では
通常は行単位のロックを使い、大量の行を一括更新する処理などではテーブル単位に切り替える、という使い分けがなされます。DBMSが自動的に判断することも多くなっています。
在庫管理での実例——ロックが足りないと何が起きるか
ある小売店で、実在庫と帳簿在庫がたびたび食い違う、という相談があったとします。
| 考えられる原因 | 確認すること |
|---|---|
| 同時実行制御が効いていない | 複数のレジや端末から同時に更新していないか |
| トランザクションの範囲が不適切 | 在庫の減算と売上の登録が別トランザクションになっていないか |
| そもそも表計算ソフトで管理している | 排他制御の仕組みがない |
3つ目がもっとも多い
第2章でも触れたとおり、表計算ソフトのファイルを共有フォルダに置いて複数人で使うと、「あとから保存した人の内容で上書きされる」という事故が起きます。これは更新の喪失そのものです。
診断士として「なぜデータベースを使うべきか」を説明するなら、容量やスピードではなく、この同時実行制御の有無を挙げるのが説得力があります。
確認してみましょう
> 次の記述の正誤を判定せよ。
> a 同時実行制御とは、複数のトランザクションが互いに干渉せず、単独で実行されたかのように制御することである。
> b 共有ロックがかかっているデータに対して、他のトランザクションが共有ロックをかけることはできない。
> c 占有ロックは、データの更新時および削除時に利用する。
解答 a:○ b:× c:○

同時実行制御とロック方式
試験のポイント
| ① | データベースAをロック | データベースBをロック |
| ② | データベースBのロック解除待ち | データベースAのロック解除待ち |
Aは「Bが解放するのを待っている」、Bは「Aが解放するのを待っている」。どちらも相手が先に動くのを待っているので、永遠に動きません。これがデッドロックです。
③ 日常の例えで
狭い廊下で2人が向かい合ったとします。互いに「お先にどうぞ」と道を譲ろうとして、同時に同じ側へ動き、またぶつかる——これを繰り返して通れなくなる状態に似ています。
あるいは、2人の料理人が1本の包丁と1枚のまな板を取り合う場面。片方が包丁を持ったまままな板を待ち、もう片方がまな板を押さえたまま包丁を待てば、どちらの料理も完成しません。
④ デッドロックを防ぐには
デッドロックの発生を防ぐためには、次の3点に留意する必要があります。
| 留意点 | 内容 |
|---|---|
| ロックの粒度 | ロックの範囲。テーブル単位の他、1行ずつのレコード単位にかけることもできる |
| ロックの種類 | 共有ロック・占有ロックのどちらを使うか |
| ロックをかける順番 | 複数のデータをロックする際の順序 |
⑤ 3つの対策がなぜ効くのか
ロックの粒度を細かくする
テーブル単位でロックすると、関係のないデータまで巻き込むため、鉢合わせの機会が増えます。レコード単位にすれば、本当に同じ行を触るときしか衝突しません。
ロックの種類を適切に選ぶ
参照するだけなのに占有ロックをかけていれば、他の参照まで待たせることになります。参照には共有ロックを使えば、待ちが減ります。
ロックをかける順番をそろえる
これがもっとも効果的です。すべてのトランザクションが「必ずAの次にB」という同じ順番でロックすると決めておけば、先ほどの膠着は起こりません。
| トランザクションA | トランザクションB | |
|---|---|---|
| ① | データベースAをロック | データベースAのロック解除待ち |
| ② | データベースBをロック | 待ち |
| ③ | 処理を完了し、両方を解放 | データベースAをロック |
| ④ | データベースBをロック |
Bは待たされますが、いずれ必ず動けます。デッドロックは「永遠に動けない」ことが問題なので、「待つが動ける」状態にできれば解決です。
⑥ 起きてしまったらどうするか
DBMSは、デッドロックを検知するとどちらか一方のトランザクションを強制的に終了(ロールバック)させます。犠牲になったほうは最初からやり直しになりますが、両方が止まったままになるよりはましだからです。
したがってアプリケーション側では、デッドロックによる強制終了を想定して、再試行する仕組みを用意しておくのが一般的です。
⑦ 名前の由来
dead lock=「死んだ錠」。開けることも閉めることもできなくなった状態を表しています。情報システム以外の分野でも、交渉が行き詰まった状態を指して「デッドロックに乗り上げる」という言い方が使われます。
具体例
受注処理と出荷処理でデッドロックが起きる場面
| 受注処理 | 出荷処理 | |
|---|---|---|
| 扱うデータ | 在庫表 → 受注表 | 受注表 → 在庫表 |
受注処理は在庫を確認してから受注を登録し、出荷処理は受注を確認してから在庫を減らします。ロックをかける順番が逆になっていることに注目してください。
同時に走ると
| 時刻 | 受注処理 | 出荷処理 |
|---|---|---|
| 1 | 在庫表をロック | 受注表をロック |
| 2 | 受注表のロックを待つ | 在庫表のロックを待つ |
| 3 | 待ち続ける | 待ち続ける |
デッドロックです。
対策——順番をそろえる
出荷処理も「在庫表 → 受注表」の順でロックするように直します。
| 時刻 | 受注処理 | 出荷処理 |
|---|---|---|
| 1 | 在庫表をロック | 在庫表のロックを待つ |
| 2 | 受注表をロック | 待ち |
| 3 | 処理完了、解放 | 在庫表をロック |
| 4 | 受注表をロック |
これで膠着は起きません。
設計段階で決めておくべきこと
デッドロックは、個々のプログラムを見ているだけでは発見できません。2つのプログラムが同時に走ったときに初めて起きるからです。
そのため、システム全体の設計段階で、
という取り決めが必要になります。第9章で学ぶ設計工程の重要性が、こうしたところに現れます。
テストで見つけにくいという厄介さ
デッドロックは、タイミングが合ったときだけ起きます。単体テストでは絶対に再現せず、結合テストでもたまたま起きないことがあります。本番稼働後、利用者が増えてから初めて表面化する——という経過をたどりがちです。
第9章で学ぶ負荷テストや長時間の運用テストが必要とされる理由のひとつが、この種の同時実行に起因する不具合です。
確認してみましょう
> 次の記述の正誤を判定せよ。
> a デッドロックとは、各トランザクションが相互に必要なデータをロックし合い、互いにロックが解除されるのを待つ膠着状態である。
> b デッドロックを防ぐには、ロックの粒度、ロックの種類、ロックをかける順番に留意する必要がある。
> c ロックの粒度はテーブル単位のみであり、レコード単位にかけることはできない。

デッドロック
試験のポイント
プレミアムプラン
¥9,800〜/ 買い切り・自動更新なし(税込)
決済はStripe(世界最高水準・PCI-DSS準拠)で安全に処理されます。カード情報は当サービスに保存されません。