バッチ処理で使う「SET TRANSACTION ISOLATION LEVEL SERIALIZABLE」の勘所

使い方に誤りがあると次のエラーが出る。

ORA-08177: このトランザクションのアクセスをシリアル化できません

どんな時にORA-08177が出るのかを検証する

sqlplusで下記のように検証してエラーを発生できる。

トランザクション

00:18:55 SQL>conn scott/scott@orcl
00:19:01 SQL>SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
トランザクションが設定されました。

00:19:06 SQL>select EMP_NAME from emp where EMP_CD = '1';
EMP_NAME

                                • -

SCOTT

00:21:04 SQL>select EMP_NAME from emp where EMP_CD = '1';
EMP_NAME

                                • -

SCOTT
トランザクション2がコミット後の参照はOK→これがSERIALIZABLEの機能
 
00:21:40 SQLupdate emp set EMP_NAME='v2' where EMP_CD = '1';
update emp set EMP_NAME='v2' where EMP_CD = '1'
*
行1でエラーが発生しました。:
ORA-08177: このトランザクションのアクセスをシリアル化できません
トランザクション2 コミット後の更新 NG

トランザクション

00:19:13 SQL>conn scott/scott@orcl
00:19:19 SQL>update emp set EMP_NAME='v' where EMP_CD = '1';
1行が更新されました。
00:20:33 SQL> commit;
コミットが完了しました。

まとめ

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;で実行時の状態のテーブル値を取得することは可能
しかし、テーブル値を更新しようとした場合は実行時の状態と同じでなければシリアル化できないエラーが発生する。
オンラインで更新されるテーブルなどを参照だけでなく更新処理も行う場合は注意。というか更新しちゃだめ。