トランザクションとは一連の処理をひとまとめにしたもので,DB(データベース)の更新には非常に重要な概念.例えば商品を注文して購入する場合以下のトランザクションが考えられる.
- トランザクション開始
- 利用者が商品を注文する
- 在庫を管理しているテーブルの街頭の商品の在庫を1減らす
- 購入者テーブルに購入者のIDを追加する
- トランザクション終了
トランザクション処理におけるACID特性
このようなデータベースには複数の利用者から同時にアクセスが来るため,データの不整合が起きないようにACID特性を担保しなければならい.ACID特性はそれぞれの頭文字からきている.
特性名 | 概要 |
---|---|
原子性 Atomicity | 「全ての処理を完了させる」または「すべての処理を行わない」の2択であること.中途で処理を終了させない. |
一貫性 Consistency | データベースの内容に矛盾が生じず,整合性が保たれていること |
独立性 Isolation | 複数のトランザクションを同時に実行させた場合に, 単独で実行した時と同じ処理結果にならなければならない. 他のトランザクションの影響を受けてはならない |
耐久性 Durability | トランザクションの更新結果は,DBに障害が発生したとしても 更新内容は保証されること |
排他制御
データベース更新時に複数のトランザクションから更新が入った場合,データ不整合が起きる可能性がある.データ不整合を防ぐために,トランザクションの更新中はアクセスをロックして,別のトランザクションから更新ができないようにする.更新中のトランザクションが終了すれば次のトランザクションの更新が行えるようになる.
排他制御を行わない場合上記の左図に該当する.ロックがかかっていないため,同時にアクセスができてしまう.本来200円にならないといけないが,700円を入れるべきか500円を入れるべきかで不整合が発生してしまう.上記の場合,後から更新された方がDBに保存されるため,少しでもユーザBが遅い場合は500円となる.引き出された金額は合計で700円なのに対し,DB上では500円しかひきだされていないことになる.
上記の右図は排他制御を行っているため,ユーザBがアクセスしようとしても,ロック中なので待ち状態となっている.ユーザAのトランザクションが終了するとロックが解除され700円を取得できる.排他制御は上記のようにロックをかけて不整合を防ぐ制御方法になる.
共有ロックと専有ロック
参照時に使用する共有ロックと,更新時に使用する専有ロックがあり,処理によってロックの種類を分ける必要がある.
共有ロック
共有ロックはデータを参照するときにロックをかける.他のトランザクションは共有ロック中のデータに参照することはできるが,更新を行うことはできない.
専有ロック
専有ロックはデータを更新するときにロックをかける.専有ロックがかかっているデータに関しては参照も更新も行うことができない.
共有ロックと専有ロックの関係性は下記の表になる.
最初のトランザクション | |||
共有ロック | 専有ロック | ||
後のトランザクション | 共有ロック | ○ | × |
専有ロック | × | × |
ロックの粒度(範囲)
ロックをかけるときにロックの範囲を大きくしすぎると,待ち状態が多く発生してしまいスループット(単位時間あたりに処理できるデータ量)が低下する.
ここでロックの範囲を小さくすると,待ち状態の発生を抑えることができる.しかし,ロックの管理数が多くなりメモリ使用料が増加するためメモリ領域を確保する必要がある.
デッドロック
複数のトランザクションが,別々のデータを専有ロックしている場合を考える.お互いに相手のロックしているデータを参照しようとしたときに,お互い待ち状態が発生する場合がある.このときお互いに専有ロックが解除されることは絶対にないので,永遠に待ち状態になり処理が中断される.この現象をデッドロックと呼ぶ.
- トランザクション1がデータAを専有ロック
- トランザクション2がデータBを専有ロック
- トランザクション1がデータBを参照するため共有ロック(専有ロック中のため開放待ち)
- トランザクション2がデータAを参照するため共有ロック(専有ロック中のため開放待ち)
- デッドロック発生!!
- ロールバックを行う
デッドロックが発生した場合,DBMSがロールバックを行う.
ロールバックとはDBで障害が発生したときやデッドロックが発生したときに,発生前までDBの状態を戻すこと.
コメント