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

Oracleトランザクション遮断レベルをSERIALIZABLEに設定すると、こんなエラーが発生することがある。今回、お客さまがマスタに1レコード追加したとたんに頻発するようになったらしい。
マニュアルによると、「このエラーが発生することを前提として」例外を捕捉しリトライするようなプログラムを書かなければいけないらしいけど、作ったの4年も前だしそんな知識なかったから、いたるところでSERIALIZABLE設定をしている。
今更そんな多くの箇所に手を入れるのも嫌だし、直近の対応として例外が発生しなくなるようにしなければいけないため、いろいろと情報を探っていたら、どうも次のような現象らしい。

Oracleは、データの記録を「データブロック」という単位で行っているが、あるレコードをどのデータブロックに割り当てるかはOracleの内部で処理されており、同じテーブルのデータだからといって同じデータブロックに割り当てられるとは限らない。逆に、全く違うテーブルのデータが同じデータブロックに割り当てられる可能性もある。
今回発生したエラーは、複数のスレッドがたまたま同時に同じデータブロックにアクセスしようとしたとき、シリアル性を保証できないために発生する例外のようだ。

Oracleのデータは、削除や追加するたびに違うデータブロックに割り当てられるので、対象データをいったん削除し、再度追加することで異なるデータブロックに再割り当てされ、競合は発生しなくなるのではないか?

ということで、お客さまにその旨連絡して、様子を見てもらうことにした。
結果がわかるのは明日以降だろうけど、これで解決できるのであればラッキー。

(追記 9/25) 本日お客様から呼び出されちゃいました orz... やはり上記手順は暫定対処でしかないので、本質的にはソース改修するしかないようです。