JDBC 与 Oracle - executeUpdate 自动更改 AutoCommit 的状态

JDBC with Oracle - executeUpdate automatically changes status of AutoCommit

提问人:AnR 提问时间:3/10/2023 更新时间:3/10/2023 访问量:185

问:

我们有一个使用连接池的 Java 应用程序。通常,在我们用来关闭 AutoCommit 的每个函数/进程的开头。在最后部分,在提交/回滚后,我们使用setAutoCommit(false);setAutoCommit(true);

有时,我们在一些函数中会遇到此异常:

java.sql.SQLException: Could not commit with auto-commit set on

经过调查,我们发现 AutoCommit 状态在没有任何明显原因的情况下随机从 OFF/false 更改为 ON/true。executeUpdate

status = connection.getAutoCommit(); // stores false
statement.executeUpdate(sQuery.toString());
status = connection.getAutoCommit(); // stores true

正如我所说,它并不总是发生。这些行之间没有其他可能更改状态的函数调用。

作为解决方法,我们在 executeUpdate 后恢复了 AutoCommit 状态(如果它发生变化)。但是我们需要知道更多,因为executeUpdate在应用程序中被使用了几十次。

有没有人遇到过类似的问题?除上述方法外,还有什么解决方案吗?

我们将 Java 1.8 与 Oracle 11 和 ojdbc8-19.3.0.0.jar 一起使用

java oracle jdbc ojdbc 自动提交

评论


答:

2赞 Jean de Lavarene 3/10/2023 #1

更合理的解释是,连接对象被多个线程同时使用,并且另一个线程更改了两个 getAutoCommit() 调用之间的自动提交模式。出于各种原因,强烈建议不要在线程之间并发共享 JDBC 连接,其中之一是您看到的行为,但您也可能最终死锁数据库会话。

JDBC 规范指出,在启用了自动提交模式的连接上调用 commit() 应该会引发异常。但是有一个 JDBC 属性可用于放宽此行为:将“oracle.jdbc.autoCommitSpecCompliant”设置为“false”。请参阅此处的 Javadoc。

评论

2赞 user16320675 3/10/2023
但“放松这种行为”更像是隐藏错误,而不是纠正错误;假设有(有效)理由/需要关闭自动提交。
0赞 Jean de Lavarene 3/10/2023
是的,放宽行为只是为了解决虚假应用程序,绝对不建议这样做。
0赞 AnR 3/10/2023
我们还怀疑多用户行为中的其他一些使用实例正在更改此属性。话虽如此,除非连接池和分配机制存在错误,否则不会在线程之间共享连接。
0赞 siggemannen 3/11/2023
由于您使用连接池,因此可能存在错误。也许你可以改变你的prolog/epilog处理代码,以记录你设置了自动提交关闭/打开的连接,看看是否以某种方式访问了多个相同的连接
0赞 siggemannen 3/11/2023
如何“释放”与池的连接?你使用什么样的游泳池