はじめに
リレーショナルデータベースは、トランザクションという単位でユーザが実行した一連の処理を管理します。このトランザクションという言葉は、それ自体が「処理」とか「取引」のような意味で使われる言葉ですが、データベースの世界では特別な意味を持った言葉として使われます。
本稿では、このトランザクションという概念がどのような意味を持っているのか、そしてDBMSがトランザクション制御のためにどんなメカニズムで動いているかを中心に解説を行います。
- 対象読者
- 「トランザクション」という言葉のイメージが湧かない人
- 長大なトランザクションがコケたときにすべてロールバックされるのは理不尽だと感じている人
- 今までブラックボックスだったデータベースの内部動作を知りたい人
- 対象環境
トランザクションとは何か?
意味的な単位としてのトランザクション
トランザクションとは、複数の検索や更新を含む処理からなる意味的な単位です。「意味的な」というのは、要するにどこからどこまでが1つのトランザクションかDBMSには自動的にわからないということです。DBMSは、ただユーザから受け取ったさまざまな命令を忠実に実行していくだけで、その命令の「区切り」がどこにあるかは知りません。したがって、「ここからここまでが1つのトランザクションである」ということは、ユーザから指定する必要があります。
そのため、SQLにはトランザクションを区切るためのコマンドがあります。WEB+DB PRESS Vol.57の特集「リレーショナルデータベース&SQL入門」でも紹介しましたが、表1のような開始と終了のコマンドを使って、DBMSにトランザクションの区切りを教えます。
表1 DBMS別トランザクション開始/終了コマンド
開始/終了 | DBMS | コマンド |
開始 | SQLServer、PostgreSQL | BEGIN TRANSACTION |
MySQL | START TRANSACTION |
Oracle、DB2 | ない |
終了 | 共通 | COMMIT/ROLLBACK |
開始コマンドがDBMSによってバラバラなのは、標準SQLで明確に決まっていないためです。中にはOracleやDB2のように、データベースへ接続したら自動的にトランザクションが始まることになっているため、開始コマンドのないDBMSもあります。確かに、最初に暗黙に開始されれば、そのあとは終了文だけあれば区切りはわかる(終了文が次のトランザクションの開始文も兼ねる)ので、合理的といえば合理的です。
構造的な単位としてのトランザクション
一方でDBMSの側から見ると、トランザクションは2つの重要な機能に関係しています。それが、「データの復旧」と「同時実行制御」です。まずは、前者から見ていきましょう。
トランザクションは復旧の単位
障害発生前に終了したトランザクション
データベースに限らず、システムというのは使い続けていればどこかのタイミングで障害に見舞われます。なるべく障害に遭遇しない堅固なシステムであることが望ましいには違いないのですが、この世界に障害のまったく起きないシステムというのは存在しません。
さてそうすると、データベースもまた障害が発生することを前提として作っておく必要があります。障害発生時、DBMSに求められる最優先事項は、データベースに格納されているデータをきちんと復旧(リカバリ)できることです。問題は、その場合の「きちんと」が何を意味するかです。リレーショナルデータベースは、この「きちんと」を次のように定義しています。
- 「障害発生前に終了しているトランザクションの結果は保証する」
これが、トランザクションが満たすべき四特性(ACID)の一つ、D(Durability:耐久性)です。障害発生までに終わっていたトランザクションについては、責任を持ってデータベースがそのデータの状態を復活させましょう、ということです。
障害発生時に実行途中のトランザクション
これは裏を返すと、障害発生時点で途中のトランザクションの結果は保証しない、ということです。バッドタイミングに実行されていた間の悪いトランザクションがどういう運命になるかというと、ロールバック、つまり「なかったこと」にされるのです。1,000万行の更新を行う長大なUPDATE文を実行して、数時間かかってようやく999万9,999行までいって最後の1行の更新中に何らかの障害が発生した、という場合、DBMSはそれまでの999万9,999行の更新を保存してくれません。すべてが無に帰し、また最初の一歩から始めるしかありません。
私も何度かこういう長大なトランザクションがあと一歩のところでコケた、という経験を持っていますが、そのときの脱力感は名状しがたいものがあります。山頂から麓まで岩が転がり落ちるのを見るシーシュポス[1]の気分というか(図1)、もう少し卑近な例だと、RPGのゲームをやっていて、ずっとセーブしないまま続けていたらパーティが全滅したときの徒労感とか、まあそんな感じです。
データベースの基本精神
運の悪い奴の面倒まで見るつもりはない。
この「すべてか、然らずんば無」という無慈悲な掟が、四特性の一つ、A(Atomicity:原子性)と呼ばれます。これは前号の特集でも紹介したので、覚えている方もいるでしょう。そこでも述べたように、RDBMSのトランザクションとは、論理的なレベルではこの原子性を保証するための概念です[2]。