PostgreSQLのトランザクション内SQLエラー対応
PostgreSQLでは、1つのトランザクション内でSQLエラーが発生した場合、後続するSQL文はすべて無条件でエラーとなります。
この状態はトランザクションに対してcommitもしくはrollbackを実行するまで続きます。
WARNING
エラーが発生している状態でcommitを実行しても実際にはrollbackされます
これはPostgreSQL固有の動作であり、通常は問題ない動作なのですが、テーブルロックエラーなどリトライ処理を行うケースで問題になります。
(SQLのリトライについてはSQL実行のリトライを参照)
uroboroSQLではリトライ指定のあるSQL実行、かつ、PostgreSQL(より正確にはDialect#isRollbackToSavepointBeforeRetry()がtrueの場合)の場合にsavepointを用いた部分ロールバックを行うことでこの問題に対応しています。
具体的にはリトライ指定のあるSQL実行、かつ、PostgreSQLの場合はSQL実行の直前にリトライ用のsavepointを設定し、SQL実行が成功すればsavepointの解放、SQL実行が失敗した場合はリトライ用のsavepointまでロールバックを行います。
TIP
リトライ指定のないSQL実行の場合はsavepointの設定は行われません。
リトライ指定のないSQLで上記と同様の動作を行う場合はsavepointScopeを利用して以下のように実装してください。
java
agent.required(() -> { // トランザクション開始
agent.savepointScope(() -> {
// savepointScopeの開始
agent.update("example/insert_product")
.param("productId", 1)
.count();
});
agent.savepointScope(() -> {
// 後続処理
int count = agent.update("department/insert_department")
.param("deptNo", 1)
.param("deptName", "Sales")
.count();
・・・
});
});