見出し画像

JAVA-tomcatの開発環境で「Cannot change transaction isolation level in the middle of a transaction」のエラーを解消する


JAVA-tomcatの開発環境で「Cannot change transaction isolation level」 のエラーが発生した

Apache tomcatとJavaの開発環境で、データベースアクセス用ライブラリを用いた運用システムで以下のエラーが頻発するようになっていた。

  • Caused by: org.postgresql.util.PSQLException: Cannot change transaction isolation level in the middle of a transaction.

postgresqlのトランザクション中に、トランザクション分離レベルを変更できないという内容自体は単純なエラー。
開発中には一度も発生したことないエラーである。

エラーの発生箇所を確認する

エラーの発生箇所を見ると、トランザクション制御はきちんとできている。

tring sql_1 = "(シンプルなinsert文)";

Connection con = null;
try  {
Sql2o sql2o = new Sql2o(DataSourceMgr.getDataSource());
con = sql2o.beginTransaction();
//SQL実行
con.createQuery(sql_1)
        .executeUpdate();

con.commit(true);
/} catch (Exception e) {
if(con != null){
con.rollback();
}
e.printStackTrace();
throw new Exception(e);
} finally {
if(con != null){
con.close();
}
}

このtry-catch内でエラーが発生している。
sql2oはデータベースアクセス用のJavaライブラリで、beginTransaction内で、

> connection.getJdbcConnection().setAutoCommit(**false**);
> 
> 
> connection.getJdbcConnection().setTransactionIsolation(isolationLevel);
>

を実行している。
autocommit = false に設定し、トランザクション分離レベルを変更しているが、postgresqlでは別トランザクションの最中にトランザクション分離レベルを変更できない。

コネクションプールのdefaultAutoCommitの設定

原因を調べると、defaultAutoCommitの設定にあることが分かった。
jdbcを使用するDB接続はコネクションプールを使用しているため、defaultAutoCommitがtrueの場合、トランザクション内でautocommit = false に設定するとcommitした後にautocommit = trueに戻すわけだが、マルチスレッド等、複数のトランザクションが並列で実行される場合、コネクションプールにあるデフォルトの設定と食い違うので、変更できないというエラーが発生するようだ。

最後に

defaultAutoCommit=falseに設定することでしばらく様子を見る。
これで解決しない場合は、更にコネクションプールの設定を見直すことになる。

お知らせ

電巧社ではセキュリティ分野専門のブログも公開しています。ゼロトラストセキュリティを始めとした、ランサムウェアへの対処法等を紹介しています。こちらもよろしくお願いします。