ITパスポート対策

トランザクション

データベースは複数の人が同時に使います。同時に使っても壊れないようにするしくみが、トランザクションと排他制御です。

トランザクションはまとめて1つの処理

銀行の振込を考えます。A口座から1万円を引き、B口座に1万円を足す。この2つは片方だけ終わってはいけません。引いた直後にシステムが止まれば、1万円がこの世から消えます。

そこで、切り離せない一連の処理をひとまとまりとして扱います。これがトランザクションです。全部成功したらその結果を確定させ、これをコミットといいます。途中で失敗したら開始前の状態に戻し、これをロールバックといいます。中途半端な状態で終わることはありません。

ACID特性

トランザクションが満たすべき4つの性質をACID特性といいます。頭文字の並びで覚えます。

性質英語意味
原子性Atomicity全部実行されるか、まったく実行されないかのどちらか
一貫性Consistency実行の前後で、決められた整合性が保たれる
独立性Isolation同時に動く他の処理から影響を受けない
耐久性Durabilityいったんコミットした結果は障害が起きても失われない

試験では性質の名前と説明文の組み合わせを入れ替えてきます。とくに紛らわしいのが原子性と耐久性です。「途中で終わらせない」が原子性、「終わったものを消さない」が耐久性です。処理中の話か、処理後の話かで見分けます。独立性は隔離性ともいい、同時実行しても1件ずつ順に実行したのと同じ結果になる、という言い方で出ます。

同時更新で起きる事故

排他制御がないと何が起きるか、在庫数が10の商品で見てみます。

  1. 処理Aが在庫数10を読む
  2. 処理Bも在庫数10を読む
  3. 処理Aが3個売れたので7を書き込む
  4. 処理Bが2個売れたので8を書き込む

本当は5個売れたので在庫は5のはずですが、結果は8になりました。処理Aの更新が処理Bに上書きされて消えています。これを更新の消失といいます。

これを防ぐのが排他制御です。あるトランザクションがデータを使っている間、そのデータに鍵をかけて他のトランザクションを待たせます。この鍵がロックです。処理Aがロックを取っている間、処理Bは読むところから待たされるので、10を読んで7になった後に処理Bが動き、正しく5になります。

ロックには2種類あります。読むだけなら他の人も同時に読んでよい共有ロック、書き込むときは他の誰にもさわらせない専有ロックです。読み手どうしは共存できるが、書き手がいるときは誰も入れない、という関係です。

デッドロック

ロックには副作用があります。処理Aが商品表をロックしたまま在庫表を待ち、同時に処理Bが在庫表をロックしたまま商品表を待つと、お互いが相手の解放を待ち続けて永久に進みません。これがデッドロックです。

対策は、資源をロックする順番を全部の処理でそろえることです。必ず商品表、次に在庫表、と決めておけば、待ちが一方向になるのでにらみ合いになりません。DBMS側でデッドロックを検知し、片方のトランザクションを強制的にロールバックして解消する方式もあります。

試験ではデッドロックの説明として「処理が終わらず互いに待ち続ける状態」が正解文になり、「ロックのかけすぎで性能が落ちること」や「更新が上書きされて消えること」が誤りの選択肢として並びます。更新の消失はロックが無いときの事故、デッドロックはロックが有るからこそ起きる事故です。ここを逆にしないでください。

生田 陸人
ゆめさくエンジニア / 現役ソフトウェアエンジニア
編集 LuaGate編集部