銀行で振込している最中に、システムが止まったらお金はどうなるんですか?
そこで登場するのがトランザクション。「引き落とし」と「入金」をひとまとまりとして扱って、途中で止まったら全部なかったことにするんだ。
トランザクション:ひとまとまりの処理
トランザクション は、データベースに対する これ以上分けてはいけない一連の処理のまとまり です。
銀行振込(AさんからBさんへ1万円)
- Aさんの口座から1万円を引く
- Bさんの口座に1万円を足す
1だけ実行されて2の前にシステムが止まると、1万円が消えてしまいます。1と2は「両方やる」か「両方やらない」かのどちらかでなければなりません。
- コミット:トランザクションの処理がすべて成功したら、結果を 確定 させる
- ロールバック:途中で失敗したら、それまでの更新を 取り消して開始前の状態に戻す
ACID特性
トランザクションが満たすべき4つの性質を、頭文字をとって ACID特性 といいます。
| 性質 | 意味 | 振込の例 |
|---|---|---|
| 原子性(Atomicity) | すべて実行されるか、まったく実行されないか | 引き落としだけ、は起きない |
| 一貫性(Consistency) | データに矛盾がない状態を保つ | 2人の残高の合計は振込の前後で変わらない |
| 独立性(Isolation) | 同時に実行しても、互いに影響しない | 別の人の振込と同時でも結果が狂わない |
| 耐久性(Durability) | 確定した結果は障害が起きても失われない | コミット後に停電しても振込は有効 |
同時に更新すると何が起きる?
ネットショップで、在庫100個の商品をAさんが30個、Bさんが20個、ほぼ同時に 注文したとします。
在庫は本当は50個なのに、データ上は80個になってしまいました。この現象を 更新の喪失(ロストアップデート)といいます。
排他制御:ロックで順番待ちさせる
これを防ぐのが 排他制御 です。あるトランザクションがデータを使っている間、そのデータに ロック(鍵) をかけて、他のトランザクションを待たせます。上の例では、AがロックをかけてAの更新が終わるまで、Bは在庫を読めません。Bは70を読んでから20を引くので、正しく50になります。
試着室の鍵 をイメージしよう。中に人がいる間は鍵がかかっていて、次の人は外で待つ。出てきたら(ロック解除)次の人が入れる。
ロックには2種類あります。
| 種類 | 使う場面 | 他のトランザクションは |
|---|---|---|
| 共有ロック(読取りロック) | データを 読む とき | 読むことはできる。書くことはできない |
| 専有ロック(排他ロック、書込みロック) | データを 更新する とき | 読むことも書くこともできない |
ロックをかける範囲を広くすると安全ですが、待ち時間が増えて 処理が遅くなります。表全体ではなく必要な行だけにロックをかけるなど、範囲を小さくする工夫がされています。
デッドロック:お互いに待ち続ける
ロックを使うと、困った状態が起きることがあります。
このように、互いに相手がロックしているデータの解除を待ち続け、処理が進まなくなる状態 を デッドロック といいます。DBMSはデッドロックを検出すると、どちらか一方のトランザクションをロールバックさせて解消します。予防策としては、すべてのトランザクションでロックをかける順番をそろえる(必ずX→Yの順にする)ことが有効です。
障害回復:ログとバックアップで元に戻す
DBMSは、データを更新するたびに ログファイル(ジャーナル)に記録を残しています。ログには 更新前の値 と 更新後の値 が記録されます。障害が起きたら、これを使って回復します。
ロールバックとロールフォワード、名前が似ていて逆になりそうです…。
back=後ろへ戻る、forward=前へ進む。途中までの処理を「なかったこと」にするのがバック、バックアップから最新まで「やり直して進める」のがフォワードだよ。
| 回復方法 | 使うもの | 戻る状態 | 主な場面 |
|---|---|---|---|
| ロールバック | 更新前 ログ | トランザクション 開始前 | 処理の途中でエラーが起きた、デッドロックの解消 |
| ロールフォワード | バックアップ + 更新後 ログ | 障害発生 直前(コミット済みの状態) | ディスクの故障(媒体障害) |
試験に出るポイント
- トランザクション:分けてはいけない処理のまとまり。成功したら コミット、失敗したら ロールバック
- ACID特性:原子性(全部か無か)・一貫性・独立性・耐久性
- 同時更新で値が狂うのを防ぐのが 排他制御(ロック)。読むときは 共有ロック、書くときは 専有ロック
- デッドロック:互いに相手のロック解除を待ち続ける状態。ロックの順番をそろえて予防
- ロールバック は更新前ログで開始前へ、ロールフォワード はバックアップ+更新後ログで障害直前へ