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

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

図1●リードコミッティドの実行例1(ダーティーリードは発生しない)
図1●リードコミッティドの実行例1(ダーティーリードは発生しない)
[画像のクリックで拡大表示]

 リードアンコミッティド分離レベルの時に発生していたダーティーリードは発生しません。トランザクション2のSQL文3は,リードアンコミッティドではCOMMIT前の不安定なデータを取得していましたが,リードコミッティドではそのような不安定なデータを取得しません。リードコミッティド分離レベルにすることで,図1のトランザクション1とトランザクション2ともに,期待する正しい結果になります。

 では次に,図2のような時系列でSQL文が処理されたケースを考えてみます。トランザクション2の分離レベルをリードコミッティドに設定しています。図1との違いは,トランザクション2のSQL文3を実行する前に,トランザクション1がCOMMITされている点です。

図2●リードコミッティドの実行例2(ファジーリード)
図2●リードコミッティドの実行例2(ファジーリード)
[画像のクリックで拡大表示]

 トランザクション2内のSQL文1により取得される商品Aの価格は,トランザクション1が開始される前(値上げ前)の商品Aの価格です。そうなると,トランザクション2のSQL文3で取得する商品Bの価格も値上げ前の価格を取得してほしいところです。ところが図2のような時系列でSQL文が処理されると,トランザクション2のSQL文3は,トランザクション1で変更した値(800円)を取得します。

 このように,自分自身以外のほかのトランザクション(今回の場合トランザクション1)にてCOMMITされた結果を読み込んでしまう(今回の場合トランザクション2が)現象を『ファジーリード』と呼びます。リードコミッティド分離レベルでは,『ダーティーリード』は発生しませんが,この『ファジーリード』が発生してしまいます(図3)。

図3●ファジーリードのイメージ
図3●ファジーリードのイメージ

 図2のようなケースでは,リードコミッティド分離レベルで実行してはいけないことが分かると思います。しかし,ファジーリードという現象は,ダーティーリードと違って,どんな場合でもダメというわけではありません。トランザクションとして確定している値を読み込むわけですから。図2のケースでは問題ですが,アプリケーションによっては問題とならないケースも多いと思われます。問題なのかどうかを判断するのは,トランザクションの要件を理解している,アプリケーション開発者の役割です。


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