DBアタマアカデミー

第2回 トランザクションを知ればデータベースがわかる―「データ復旧」「同時実行制御」を行う“不完全な”しくみ(1)

この記事を読むのに必要な時間:およそ 2 分

はじめに

リレーショナルデータベースは,トランザクションという単位でユーザが実行した一連の処理を管理します。このトランザクションという言葉は,それ自体が「処理」とか「取引」のような意味で使われる言葉ですが,データベースの世界では特別な意味を持った言葉として使われます。

本稿では,このトランザクションという概念がどのような意味を持っているのか,そしてDBMSがトランザクション制御のためにどんなメカニズムで動いているかを中心に解説を行います。

対象読者
  • 「トランザクション」という言葉のイメージが湧かない人
  • 長大なトランザクションがコケたときにすべてロールバックされるのは理不尽だと感じている人
  • 今までブラックボックスだったデータベースの内部動作を知りたい人
対象環境
  • すべてのリレーショナルデータベース

トランザクションとは何か?

意味的な単位としてのトランザクション

トランザクションとは,複数の検索や更新を含む処理からなる意味的な単位です。「意味的な」というのは,要するにどこからどこまでが1つのトランザクションかDBMSには自動的にわからないということです。DBMSは,ただユーザから受け取ったさまざまな命令を忠実に実行していくだけで,その命令の「区切り」がどこにあるかは知りません。したがって,「ここからここまでが1つのトランザクションである」ということは,ユーザから指定する必要があります。

そのため,SQLにはトランザクションを区切るためのコマンドがあります。WEB+DB PRESS Vol.57の特集「リレーショナルデータベース&SQL入門」でも紹介しましたが,表1のような開始と終了のコマンドを使って,DBMSにトランザクションの区切りを教えます。

表1 DBMS別トランザクション開始/終了コマンド

開始/終了DBMSコマンド
開始SQLServer,PostgreSQLBEGIN TRANSACTION
MySQLSTART TRANSACTION
Oracle,DB2ない
終了共通COMMIT/ROLLBACK

開始コマンドがDBMSによってバラバラなのは,標準SQLで明確に決まっていないためです。中にはOracleやDB2のように,データベースへ接続したら自動的にトランザクションが始まることになっているため,開始コマンドのないDBMSもあります。確かに,最初に暗黙に開始されれば,そのあとは終了文だけあれば区切りはわかる(終了文が次のトランザクションの開始文も兼ねる)ので,合理的といえば合理的です。

構造的な単位としてのトランザクション

一方でDBMSの側から見ると,トランザクションは2つの重要な機能に関係しています。それが,「データの復旧」「同時実行制御」です。まずは,前者から見ていきましょう。

トランザクションは復旧の単位

障害発生前に終了したトランザクション

データベースに限らず,システムというのは使い続けていればどこかのタイミングで障害に見舞われます。なるべく障害に遭遇しない堅固なシステムであることが望ましいには違いないのですが,この世界に障害のまったく起きないシステムというのは存在しません。

さてそうすると,データベースもまた障害が発生することを前提として作っておく必要があります。障害発生時,DBMSに求められる最優先事項は,データベースに格納されているデータをきちんと復旧(リカバリ)できることです。問題は,その場合の「きちんと」が何を意味するかです。リレーショナルデータベースは,この「きちんと」を次のように定義しています。

  • 「障害発生前に終了しているトランザクションの結果は保証する」

これが,トランザクションが満たすべき四特性(ACID)の一つ,DDurability:耐久性)です。障害発生までに終わっていたトランザクションについては,責任を持ってデータベースがそのデータの状態を復活させましょう,ということです。

障害発生時に実行途中のトランザクション

これは裏を返すと,障害発生時点で途中のトランザクションの結果は保証しない,ということです。バッドタイミングに実行されていた間の悪いトランザクションがどういう運命になるかというと,ロールバック,つまり「なかったこと」にされるのです。1,000万行の更新を行う長大なUPDATE文を実行して,数時間かかってようやく999万9,999行までいって最後の1行の更新中に何らかの障害が発生した,という場合,DBMSはそれまでの999万9,999行の更新を保存してくれません。すべてが無に帰し,また最初の一歩から始めるしかありません。

私も何度かこういう長大なトランザクションがあと一歩のところでコケた,という経験を持っていますが,そのときの脱力感は名状しがたいものがあります。山頂から麓まで岩が転がり落ちるのを見るシーシュポス注1の気分というか図1),もう少し卑近な例だと,RPGのゲームをやっていて,ずっとセーブしないまま続けていたらパーティが全滅したときの徒労感とか,まあそんな感じです。

図1 せっかく山頂近くまで岩を持ち上げたのに…

図1 せっかく山頂近くまで岩を持ち上げたのに…

データベースの基本精神
運の悪い奴の面倒まで見るつもりはない。

この「すべてか,然らずんば無」という無慈悲な掟が,四特性の一つ,AAtomicity:原子性)と呼ばれます。これは前号の特集でも紹介したので,覚えている方もいるでしょう。そこでも述べたように,RDBMSのトランザクションとは,論理的なレベルではこの原子性を保証するための概念です注2)。

注1)
ギリシア神話に登場する人物。ゼウスの怒りを買って,巨大な岩を山頂まで上げる罰を受けた。この岩は,山頂近くまで上がるとまた麓に落ちてしまう。
注2)
この掟はあまりに無慈悲過ぎるのではないか,という意見は昔からあって,トランザクションが途中で失敗しても,部分的に結果を保存できるための方法が考えられてきました。たとえば,SAVEPOINT付きの細分化されたトランザクションや,入れ子トランザクションを使う方法がそうです。しかし,こうした非伝統的なしくみは,ACIDのAやDを犠牲にする必要があるため,利用には慎重を期す必要があります。

著者プロフィール

ミック

SI企業に勤務するDBエンジニア。主にデータウェアハウス業務に従事している。自身のサイト「リレーショナル・データベースの世界」でデータベースとSQLについての技術情報を公開している。『Web+DB Press』で「SQLアタマアカデミー」を連載中。

著書:『SQL ゼロからはじめるデータベース操作』(翔泳社,2010)『達人に学ぶ SQL徹底指南書』(翔泳社,2008)訳書:J.セルコ『SQLパズル 第2版』(翔泳社,2007)

DBアタマアカデミー:サポートページ

コメント

コメントの記入