トランザクション処理をどのようなものととらえていますか?

 ひょっとしたら,「更新処理=トランザクション処理」と考えている方がいるかもしれません。また,更新処理のプログラムを記述するのと同様に,トランザクション処理も記述するもの,と思っている方がいるかもしれません。

 このどちらも正しいとはいえないでしょう。更新処理とトランザクション処理は別物ですし,トランザクション処理を実現する仕組みはRDBMSに機能として備わっています。第1回では更新処理とトランザクション処理の概要,および,それらの違いを説明します。

 まずは,本連載で使用するサンプル・データベースを見ていきましょう。テーブルは二つあります(表1表2表3表4)。

表1●販売実績テーブルの定義
表1●販売実績テーブルの定義
表2●販売実績テーブルのカラム値
表2●販売実績テーブルのカラム値
表3●顧客テーブルの定義
表3●顧客テーブルの定義
表4●顧客テーブルのカラム値
表4●顧客テーブルのカラム値

 一つは[販売実績]テーブルで,いつどの商品を誰にいくらで販売したかを記録しているテーブルです。[販売実績]テーブルには200件のレコードが格納されているものとします。もう一つは[顧客]テーブルで,顧客の属性や,その顧客が今までに購入した商品金額の総額を格納しています。[顧客]テーブルの[総額]カラムの値は,[販売実績]テーブルに格納している値を集計すれば計算できるものです。冗長と思われたかもしれませんが,例題として使用するために意図的に付けています。なお,[顧客]テーブルには30件のレコードが格納されているものとします。

 ここから具体的な例です。「2007年11月20日に顧客番号1001の日経太郎さんに商品番号3000の商品を500円で販売した」とします。これをサンプル・データベースに反映させるには,(1)[顧客]テーブルの,日経太郎さんのレコードの[販売総額]カラムに500を加算し,(2)[販売実績]テーブルに1件のレコードを挿入する,という処理をアプリケーションに記述する必要があります。(1)(2)はそれぞれ,次のSQL文になります。

(1)の処理:顧客テーブルを更新

 [SQL文1]
 UPDATE 顧客テーブル SET 販売総額 = 販売総額+500 WHERE 顧客番号 = 1001;

(2)の処理:販売実績テーブルにレコードを1件挿入

 [SQL文2]
 INSERT INTO 販売実績テーブル VALUES (‘20071120’,3000,1001,500);

 SQL文1ではUPDATE文を使用しています。この文を受け取ったRDBMSは,テーブル内の特定のレコードのカラム値を更新します。SQL文2ではINSERT文を使用しています。この文を受け取ったRDBMSは,テーブルにレコードを追加します。

 もしプログラム開発を経験したことがあれば,テキスト・ファイルの特定の値を修正するプログラムや,テキスト・ファイルに値を追加するプログラムを思い浮かべてください。UPDATE文やINSERT文は基本的にこれらと同じです。

 さて,SQL文1とSQL文2でデータベースを更新することが分かりましたが,これで十分なのでしょうか。この例では『2007年11月20日に顧客番号「1001」の日経太郎さんに商品番号「3000」の商品を500円で販売した』という一連の事実をデータベースに記録したいわけで,SQL文1とSQL文2がともに正常に処理されることが求められます。つまり,どちらか一方だけが正常処理されたといった状態はあってはいけません。これが,トランザクションの考え方です。

 RDBMSにはトランザクション機能が実装されており,その機能を使えば,トランザクションを開始してから終了するまでのSQL文のうち,一つでも正常に処理されなければすべてのSQL文の処理をキャンセルすることができます。

 実際のトランザクション処理の流れは開発言語によって多少異なりますが,通常以下のようになると思います。

  1. AUTOCOMMITモードをOFFにする
  2. SQL文1を実行する
  3. SQL文2を実行する
  4. COMMITもしくはROLLBACKを実行する

 「AUTOCOMMITモード」をOFFに設定するということは,明示的にトランザクションを終了させない限り,たとえ複数のSQL文があってもそれらを一つのトランザクションにする,ということです。トランザクションの終了は「COMMIT」か「ROLLBACK」になります。「COMMIT」は一連のSQL文の処理を確定することで,「ROLLBACK」は一連のSQL文の処理をキャンセルすることです。上記の場合,SQL文1の処理が始まる直前にトランザクションが開始されます。

 誤解しないでほしいのは,トランザクションは複数のSQL文を一まとめにして扱うことと同じ意味ではありません。例えば,『顧客番号1002の日本花子さんの年齢を+1する』といった処理は一つのSQL文で記述できますが,これも一つのトランザクションと考えることができます。なお,AUTOCOMMITモードをONにしておくと,1トランザクション=1SQL文となります。

 このようにデータベース内の様々なデータを更新する処理とトランザクションというものは,密接な関係がありますが,同一のものでは無いことをよく理解してください。


藤塚 勤也(ふじづか きんや)
NTTデータ 基盤システム事業本部
オープンソース開発センタ 技術開発担当
シニアスペシャリスト
 沖電気工業,タンデムコンピューターズ(現日本HP)を経て,2003年より株式会社 NTTデータに勤務。現在は,オープンソース・ソフトウエアを活用したエンタープライズ・システム向けの技術開発・技術支援に従事しており,特にシステムの中核であるRDBMSに注力している。「RDBMS解剖学」(翔泳社)を共著