他のバージョンの文書 13 | 12 | 11 | 10 | 9.6 | 9.5 | 9.4 | 9.3 | 9.2 | 9.1 | 9.0 | 8.4 | 8.3 | 8.2 | 8.1 | 8.0 | 7.4 | 7.3 | 7.2

9.4. シリアライザブル隔離レベル

シリアライザブルは、トランザクションの隔離としては最も厳密なものです。このレベルではトランザクションが同時にではなく、次から次へと、あたかも順に実行されているように遂次的なトランザクションの実行を模倣します。しかし、このレベルを使ったアプリケーションでは、直列化(シリアライゼーション)の失敗によるトランザクションの再実行に備えておく必要があります。

トランザクションがシリアライザブル隔離レベルにあるときに SELECT文を実行したら、トランザクションが開始される前までにコミットされたデータのみを参照し、コミットされていないデータやそのトランザクションの実行中に別のトランザクションで更新されたデータを参照しないことが判ります。(しかし、SELECT文では同じトランザクションで行われた、まだコミットされていないデータを参照します)。SELECT文では、トランザクション内のこの問い合わせが行われ始めた状態ではなく、トランザクションそのものの始まったときの状態のスナップショットを参照するという点でリードコミッティドレベルとは異なっています。

UPDATE 文(あるいは DELETE 文または SELECT FOR UPDATE 文)で処理対象となっている行が同時に実行されていて、まだコミットされていないトランザクションによってすでに更新されている場合、その行を更新する後のトランザクションは前のトランザクションが終了してコミットされるか、ロールバックされるまで待ちます。ロールバックされた場合、次に待機しているトランザクションは該当するデータを更新できます。同時実行のトランザクションがコミットされた場合は、シリアライザブルトランザクションは下記のメッセージを表示してロールバックします。

ERROR:  Can't serialize access due to concurrent update

これは、シリアライザブルトランザクションでは、トランザクションが実行された後に別のトランザクションによって更新されたデータは変更できないためです。

アプリケーションがこのエラーメッセージを受け取った場合、現在のトランザクションを中断して、トランザクション全体を始めからやり直されなければなりません。2回目では、トランザクションはコミットされた変更含めてをデータベースの最初の状態とみなすので、新しいバージョンの行を新しいトランザクションにおける更新の始点としても、論理的矛盾は起こりません。更新トランザクションのみ再実行する必要があります。読み込み専用トランザクションでは直列化(シリアライゼーション)の衝突は決して起こりません。

シリアライザブルトランザクションレベルは、すべてのトランザクションが一貫したデータベースの状態を参照できることを保障します。ししかしながら、同時にトランザクションの更新を行うことで、今までずっと逐次実行しているように見せかけてきたものが破綻してしまいそうな場合、アプリケーションはトランザクションを再実行する覚悟をしておかなければならなくなります。そうなると、特に複雑なトランザクションの場合、再実行のコストが無視できないものになるでしょう。したがって、このレベルは、リードコミッティドでは誤った結果を表示させてしまう可能性がある、論理的にかなり複雑な問い合わせを実行するときのみに使用することをお勧めします。