トランザクションのACID特性
データベースに対するひとまとまりの処理をトランザクション(transaction) と呼ぶ。
一つのトランザクションが複数のSQL文から構成されることがある。
この場合には、もしもすべてのSQL文の実行が終わっていない状態で処理を中断してしまうと、データベースの内容に矛盾が生じてしまう。
トランザクションの例として、 銀行の振込み処理が、 よく取り上げられる。例えば、AさんがBさんに1万円振り込むとしよう。このトランザクションは、Aさんの口座の残高をー1万円で更新するUPDATE文と、Bさんの口座の残高を+1万円で更新するUPDATE文という、2つのSQL文から構成される。
もしも、Aさんの口座の残高を1万円で更新するUPDATE文を実行した 時点でシステムに障害が発生して処理が中断すると、 Aさんは振り込んだのに、Bさんが受け取っていないという矛盾が生じてしまう。
複数のSQL文から構成されていても、 トランザクションは、1つのまとまった処理であり、それ以上分割することはできない。 これをトランザクショ ンの原子性 (Atomicity) と呼ぶ。
トランザクションには、「原子性」のほかにも、一貫性 (Consistency)、 独立性 (Isolation)、 耐久性 (Durability) という特性があり、これらをまとめてACID (アシッド) 特性と呼ぶ。 ACID は、4つの特性の頭文字を取ったものである。
DBMSは、 トランザクションのACID特性を保つ機能を装備している。
| 特性名 | 読み方 | 内容の説明 | 具体例 |
|---|---|---|---|
| A:Atomicity | アトミシティ(原子性) | トランザクションの中の処理は「すべて実行される」か「まったく実行されない」かのどちらかであること。途中で止まったり、一部だけ反映されることはない。 | 銀行振込で「Aさんの口座から引き落とし」だけ実行されて「Bさんへの入金」がされないような状態にならない。両方成功または両方失敗。 |
| C:Consistency | コンシステンシ(一貫性) | トランザクションの実行前後で、データの整合性(ルールや制約)が常に保たれること。 | 残高がマイナスにならない、合計金額の整合が取れているなど、ルールが常に守られる。 |
| I:Isolation | アイソレーション(独立性) | 複数のトランザクションが同時に実行されても、互いの処理結果に影響を与えないこと。 | 2人が同時に同じ商品を購入しても、在庫数が正しく減り、重複して販売されない。 |
| D:Durability | デュラビリティ(耐久性) | トランザクションが完了(コミット)したら、その結果は永続的に保存され、システム障害が起きても失われないこと。 | データベースに保存完了後、停電が起きても更新内容が保持されている。 |
ロールバックとロールフォワード
トランザクションを構成するすべてのSQL文の実行が完了することをコミット (commit) すると呼ぶ。
もしも、 トランザクションを開始して、まだコミットしていない状態でシステムに障害が発生すると、原子性が保てなくなり、データベースの内容に矛盾が生じてしまう。
この場合には、DBMSがロールバック (rollback) という処理を行って、データベースの内容を、 トランザクションの開始前の状態に戻す。 トランザクションは、それ以上分割できないものなので、 中途半端な状態で終われないからである。コミットできないなら、 トランザクションの開始前の何も処理していない状態に戻す。
さらに、DBMSには、ロールバックによって取り消されたトランザクンを再実行する機能もあり、これをロールフォワード (roll forward)と呼ぶ。 ロールフォワードは、システムの障害時だけでなく、 システムの故障時からのデータ復旧でも行われる。
ロールバックとロールフォワードを実施するときには、トランザクション開始前およびコミット後の処理内容を記録したファイルが使われる。 これをジャーナルファイルやログファイルと呼ぶ。
ロストアップデートと排他制御
DBMSは、同時に複数のトランザクションを実行することができる。ただし、実際には、まったく同時に実行されているのではなく、全体を小さな処理に分けて、順番に切り替えて実行しているのである。
例えば、Aさんの口座を+1万円するトランザクションX と、同じAさんの口座を+2万円するトランザクションYが、同時に実行されたとしよう。
それぞれのトランザクションは、「現在の残高を読み出す」 「読み出した残高を更新する」 「更新した残高を書き込む」 という3つの小さな処理に分けられて実行されるとする。
この場合に、もしも、 下図に示した①→②→③→④→⑤→⑥の順序で処理が切り換わると、 データベースの内容に矛盾が生じてしまう。Aさんの口座は、+1万円と+2万円を合わせて13万円になるはずだが、1万円が失われて12万円になってしまうからである。

このような現象をロストアップデート (lost update) と呼ぶ。 これは、 更新 (アップデート) が失われる (ロスト) という意味である。 DBMSには、 ロストアップデートを防ぐための機能が用意されていて、これを排他制御と呼ぶ。 これは、 1つのトランザクションの実行が完了するまで、他のト ランザクションの処理を実行させない(他のトランザクションに切り換わらないようにする) 機能である。
データにロックをかける
排他制御によって、他のトランザクションを実行させないようにすることをロックと呼ぶ。他のトランザクションが入ってこないように、鍵 (lock) をかけるイメージである。ロックの形式には、データの登録、更新、削除のときにかける専有ロックと、データの読み出しのときにかける共有ロックがある。
データに専有ロックをかけると、他のトランザクションから一切の処理ができなくなる。 これは、他のトランザクションから専有ロックも共有ロックも受け付けないという意味である。 これによって、他の誰からも見られることなく、安心してデータを操作できる。
データに共有ロックをかけると、他のトランザクションから登録、更新。 削除ができなくなるが、 読み出しはできる。 これは、他のトランザクションから専有ロックを受け付けないが、共有ロックなら受け付けるという意味である。 データを見ているだけなので、他の誰かが見ても矛盾は生じない。
デッドロック
ロックをかけるときには、 注意が必要である。 ロックがかけられたデータを、 他のトランザクションが利用したいときには、ロックが解除されるのを待つことになる。例えば下図のように、トランザクションAがロックしたデータの解除をトランザクションBが待ち、 トランザクションBがロック したデータの解除をトランザクションAが待つ状態になると、どちらも処理を進められない。この状態をデッドロック (dead lock) と呼ぶ。

データベースを操作する際には、 デッドロックにならないように トランザクションの内容と実行する順序を工夫する必要がある。 DBMSの中には、デッドロックを検知すると、自動的にロールバックを行うものもある。
(参考)情報処理教科書 出るとこだけ!基本情報技術者[科目A][科目B]2025年版


コメント