今回は分離レベルの「リピータブルリード」を説明します。テーブルトランザクションは,連載の第1回で説明したものを使います。

 まず,前回説明した「リードコミッティド」との違いを理解するために,トランザクション2の分離レベルをリピータブルリードに設定し,前回と同じ時系列でトランザクション1とトランザクション2のそれぞれのSQL文が実行された場合を見てみます(図1)。

図1●リピータブルリード(ファジーリード発生しない)
図1●リピータブルリード(ファジーリード発生しない)
[画像のクリックで拡大表示]

 リードコミッティドの時に発生していたファジーリードは発生しません。トランザクション2のSQL文3は,リードコミッティドではトランザクション2を開始した後に(別のトランザクションで)COMMITされたデータを取得していましたが,リピータブルリードではそのようなデータを取得しません。リピータブルリード分離レベルにすることで,図1のトランザクション1とトランザクション2ともに,期待する正しい結果になります。

 ここで,1つ疑問がわくかも知れません。そもそも非常にゆるいリードアンコミッティドやリードコミッティドの分離レベルなど不要ではないかと。押さえておきたいことは,RDBMSからするとリピータブルリード分離レベルは,リードアンコミッティドやリードコミッティドに比べると非常に処理負担が大きい,ということです。

 今回の例で説明しましょう。ファジーリードを発生させないようにするには,たとえトランザクション1が正常にCOMMITされたとしても,トランザクション1のCOMMITより先に開始されたトランザクションが全て終了するまで,トランザクション1内で実行された更新処理の変更前データを保持し,適切に参照できるようにしておかなければなりません。この実装方法は,RDBMSによって異なります。ただどのRDBMSにとっても,この仕組みは処理負担が重く,処理性能の低下を招く可能性があります。アプリケーション開発者は,実現したいトランザクションの要件を十分に理解し,できるだけRDBMSに負担をかけない分離レベルでトランザクション処理を実行するよう心がける必要があります。

 さて,トランザクションの分離レベルは4種類あり,リピータブルリードは3番目にゆるい分離レベルです。ということは,リピータブルリード分離レベルでも,ある条件によっては不都合が発生する場合があるということです。

 その不都合を説明するために,もう1つ別のトランザクションを追加し,それをトランザクション3とします(図2)。このトランザクションは,『顧客番号1001の人の商品別販売金額と,全販売件数を抽出する』というものです。以下の2つのSQL文を実行する必要があります。

■トランザクション3
[SQL文1] 商品別販売金額を取得する
SELECT 商品番号,SUM(販売金額) FROM 販売実績
WHERE 顧客番号 = 1001 GROUP BY 商品番号;
[SQL文2] 全販売件数を取得する
SELECT COUNT(*) FROM 販売実績;
図2●トランザクション3

 では,このトランザクション3をリピータブルリード分離レベルに設定し,図3のような時系列でトランザクション2と同時に実行されるとどのようなことが起こるでしょうか。

図3●リピータブルリード(ファントムリード)
図3●リピータブルリード(ファントムリード)
[画像のクリックで拡大表示]

 トランザクション2が開始される前の販売実績テーブルには100件のレコードが格納されています。トランザクション3のSQL文1を実行した時にはトランザクション2はまだCOMMITしていないので,トランザクション2の開始前の状態を対象に結果を取得します。ところが,トランザクション3のSQL文2を実行した時にはトランザクション2はCOMMITで終了しているので,トランザクション2で追加したレコード2件を含んだ結果を取得しています(この場合102件)。一つのトランザクションであるにもかかわらず,一つめのSQL文を実行するときの対象レコード数と,二つめのSQL文を実行するときの対象レコード数は異なっています。

 トランザクション2での追加処理が,トランザクション3に影響を及ぼしてしまっています。この現象を『ファントムリード』と呼びます。ファジーリードは更新処理に対するもので,ほかのトランザクションでUPDATEされた値を読み込んでしまう現象です。一方,ファントムリードは追加処理に対するもので,ほかのトランザクションでINSERTされたレコードを読み込んでしまう現象です(図4)。

図4●ファントムリードのイメージ
図4●ファントムリードのイメージ

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