複数のデータベースを相手に
トランザクションを実行するために
図1●データベースの概念と実際![]() |
現在広く利用されているリレーショナル・データベース管理システムは,一つのデータベースに対してトランザクションを実行している限り,データに矛盾を生じるようなことがないように,十分配慮されています。
トランザクションのルールは厳しい
「ACID特性」という言葉はご存じでしょうか。トランザクションは以下の四つの特性を備えていなければいけないというものです。
(1)Atomicity(原子性):トランザクションを一度実行し始めたら,完全に実行する(コミットする)か,完全に前の状態に戻す(ロールバックする)かいずれかでなければならない
(2)Consistency(一貫性):トランザクションの前後で,データベースのデータに矛盾が生じてはならない
(3)Isolation(隔離性):同時に複数のトランザクションを実行しても,順番に実行しても結果が同じでなければならない
(4)Durability(耐久性):トランザクションが成功した場合は,その後に障害が発生してもデータベースの内容を正しく復元できなければならない
システムを開発する際,これらの仕組みをすべて自分でコーディングしようとすると,大変なことになるのは容易に想像がつくでしょう。データベース管理システムは,トランザクションが満たすべきこれら四つの仕組みを提供してくれています。
複数データベースでのトランザクション処理は難しい
複数のデータベースにまたがるトランザクション(分散トランザクションといいます)を処理しようとすると,ACID特性を満足させるのは,さらに大変になります。分散トランザクションを実行するアプリケーションは,もとのトランザクションを複数のデータベースそれぞれへのトランザクションに分けて実行し,すべてのデータベースで不整合が生じない状態でコミットしなければいけません。
この過程の途中でなにか問題があった場合は,すべてのデータベースを正しくロールバックさせる必要があります。ここまでできれば(1)の原子性と(2)の一貫性は確保できそうですが,(3)の隔離性はどうしよう,なんて考え出すと,もう頭が痛くなってしまいます。
この頭の痛い問題を正しく実行する方法が「2フェーズ・コミット」です。2相コミットともいいます。例を挙げて説明しましょう。クッキー銀行の口座から1000円,キャンディ銀行の口座に振り込む分散トランザクションを考えます。まずクッキー銀行の口座から1000円マイナスするトランザクションを実行します。つぎにキャンディー銀行の口座に1000円プラスするトランザクションを実行します。
二つのデータベースに実行させるトランザクションは,それぞれ別々にコミットさせずに,「コミットの準備をしなさい」という命令を送って,両方から「コミット可能です」という返事を受け取った場合に限って,両方へ「コミット実行」の命令を送ってコミットさせます。
どちらかのデータベースから「コミットできない」という返事を受け取った場合や,いずれかのトランザクションで異常が発生した場合は,両方をロールバックさせます。これで万事うまくいき,クッキー銀行の口座から1000円減ったのに,キャンディー銀行の口座が1000円増えない,というような事態を回避できます。
2フェーズ・コミットの機能は,EJB(Enterprise JavaBeans)をはじめとする多くのアプリケーション開発環境や,TP(トランザクション処理)モニターなどのミドルウエアが提供しています。