Skip to content

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();
      ・・・
  });
});