トランザクションの隔離レベル

 複数のトランザクションが同時実行され,ほぼ同時に同じデータにアクセスした場合,表1に示した3種類の問題が発生する。これらを回避するために,SQLの規格では,「READ UNCOMMITTED」「READ COMMITTED」「REPEATABLE READ」「SERIALIZABLE」という4種類の隔離レベルを定義している。「READ UNCOMMITTED」が隔離レベルが一番低く,「SERIALIZABLE」が隔離レベルが一番高い。隔離レベルが高ければ高いほど,これらの問題の発生を防げるが,エラーになってトランザクション自体を実行できないこともあり得る。

表1●複数のトランザクションを同時実行した場合に発生する問題
表1●複数のトランザクションを同時実行した場合に発生する問題
[画像のクリックで拡大表示]

 PostgreSQLではREAD COMMITTEDとSERIALIZABLEのみが実装されている*1。先ほどの図1では,COMMITを発行するまでは,その他のトランザクションからは変更したデータを参照できなかった。これは,デフォルトで「READ COMMITTED」という隔離レベルが設定されているためだ。

 READ COMMITTEDに設定されている場合,トランザクションの実行中でも他のトランザクションによる更新処理や削除処理が行われれば,それらの処理が完了した時点から更新されたデータが参照されるようになる。一方,SERIALIZABLEに設定されている場合,トランザクションの実行中は他のトランザクションによるデータの更新処理や削除処理に関係なく,トランザクションが開始した時点のデータが参照される。つまり,SERIALIZABLEでは,他のトランザクションから完全に隔離された状態になる。

 それでは,READ COMMITEDとSERIALIZABLEにおける動作の違いを見てみよう。図2がREAD COMMITEDに,図3がSERIALIZABLEに隔離レベルを設定して,2つのトランザクションを実行した例だ。

図2●隔離レベルを「READ COMMITTED」に設定
図2●隔離レベルを「READ COMMITTED」に設定
トランザクションの実行中にコミットされて更新されたデータがあれば,他のトランザクションから更新されたデータが参照される。
[画像のクリックで拡大表示]

図3●隔離レベルを「SERIALIZABLE」に設定
図3●隔離レベルを「SERIALIZABLE」に設定
トランザクションの実行中にコミットされて更新されたデータがあっても,更新する以前のデータが参照される。
[画像のクリックで拡大表示]

 SERIALIZABLEの場合,隔離レベルが高いため,SELECTコマンドで検索した結果に基づいてデータを更新しようとした場合に,その他のトランザクションが該当データを先に更新してコミットしていたりすると,エラーになってしまう可能性がある。

 いったんエラーが出ると,先に説明したようにすべてのコマンド実行が成功しなければそのトランザクションは一切実行されないルールにより,そのトランザクションは自動的にアボートされる。その後SQLコマンドを実行しても(仮にそのSQLコマンドが正しいものだとしても)コミットされない。隔離レベルは状況に応じて使い分ける必要がある。

 今回までで,基本となるSQLコマンドは一通り解説した。次回は,他のアプリケーションとの連携例として,オープン・ソースのオフィス・ソフト「OpenOffice.org」との連携方法を紹介する。

出典:日経Linux 2006年9月号 155ページより
記事は執筆時の情報に基づいており、現在では異なる場合があります。

ここからは会員の登録が必要です。