トランザクションは,「関連した複数の処理をひとまとめに実行する仕組み」である。複数のユーザーがデータベースを同時利用する上で欠かせないものであり,しっかりその概念を理解しておこう。

 前回までは,1ユーザーがデータの検索や登録,削除,更新といった操作を一つひとつ実行する場合を前提に,データベースの操作方法を説明してきた。ただし,実際の利用法では,一つのSQLコマンドだけでは完結しない処理が発生する。例えば,銀行口座を扱うデータベースがあったとしよう。Aさんの口座からBさんの口座に1万円を振り込むときには,次のような2つの処理に分けて,SQLコマンドを発行する。

(1)Aさんの口座から1万円を引く

(2)Bさんの口座に1万円を足す

 このように,2つのSQLコマンドが実行されてはじめて,「1万円を振り込む」という処理が完了する。この例では,「1万円を振り込む」という処理が,一つのトランザクションになる。このトランザクションは,2つのSQLコマンドで構成され,そのうちの一つだけでは意味をなさない。2つのSQLコマンドがきちんと実行されてはじめて,「1万円を振り込む」という処理になる。

トランザクションの必要性

 ではなぜ,トランザクションが必要なのか。トランザクションがないと,一連の処理の途中でエラーが発生したり,複数ユーザーがデータベースに同時アクセスしたりする際に,データの整合性を保てないからだ。

 分かりやすいように,具合例を示しながら,トランザクションの必要性と特徴を説明していこう。

○成功しなければ更新しない

 (1)の「Aさんの口座から1万円を引く」処理を行うときに,例えば,残高が1万円よりも少なかったら1万円は引き出せない。(1)の処理が失敗したにもかかわらず,(2)の「Bさんの口座の残高に1万円を足す」という処理をしてしまうと,おかしなことになる。

 (1)と(2)の処理をトランザクションとして扱うことで,すべてのSQLコマンドが成功しない限り,データベースは更新されない。(1)または(2)の処理が失敗した時点で,それらの処理は全部実行されなかったことになる。これにより,データの不整合が起きることを防げる。

○処理の完了まで更新結果は見せない

 Aさんの口座の残高が10万円,Bさんの口座の残高が3万円としよう。両者の口座の残高の合計金額を計算すると13万になる。しかし振り込み処理をしている最中に,合計金額を計算するとどうなるだろう。

 例えば,(1)の処理が終了し,(2)の処理が実行される前の状態では,残高の合計金は12万円になってしまう。これは正確な数字ではない。

 トランザクションには,後述する「トランザクションの隔離」という仕組みがあり,処理がすべて完了するまでは,トランザクション開始前の状態に見せる。処理中にほかのユーザーが残高を参照しても,Aさんの口座の残高が10万円,Bさんの口座の残高が3万円となる。

トランザクション関連SQLコマンド

 トランザクションを利用するために最小限覚えなければならないSQLコマンドは,次の3つだ。


BEGIN:トランザクションの開始
COMMIT:トランザクションの確定と終了
ABORT:トランザクションの中止

 PostgreSQLでは「BEGIN」を発行すると,トランザクションが開始される。複数のSQLコマンド(クエリー)を実行した後,すべてを確定させ,データベースに反映させるには「COMMIT」(コミット)を,すべてを確定せずにトランザクションを終了させるには「ABORT」(アボート)を用いる。

 では,実際にトランザクションを確認してみよう。今回も,sampleデータベースを利用する。トランザクションの機能を実感するには,複数のユーザーがデータベースに接続して処理するのがよい。ターミナルを2つ立ち上げ,同時にデータベースに接続しよう。

 図1が標準の動作だ。データベースを更新しても,COMMITを発行するまでは,他のユーザー(または他のトランザクション)からは変更したデータを参照できないことが分かる。

図1●トランザクションを利用したときの動作
図1●トランザクションを利用したときの動作
COMMITを発行するまでは,他のユーザー(または他のトランザクション)からは変更したデータを参照できない。
[画像のクリックで拡大表示]