使用连接池一段时间后自动提交更改为 TRUE

Posted

技术标签:

【中文标题】使用连接池一段时间后自动提交更改为 TRUE【英文标题】:Auto-commit changes to TRUE after a while using a connection pool 【发布时间】:2012-07-09 09:13:36 【问题描述】:

我遇到了一些奇怪的问题。

我使用池来创建和管理数据库连接,我将DefaultAutocommit 选项设置为FALSE

但过了一会儿,当发生错误并调用 rollback 时,会抛出异常:Can't call rollback when autocommit=true

重新启动 JBoss 将解决问题,因为将创建一个新的 DataSource。

这是我创建数据源的方式:

protected DataSource getDataSource(String driverClassName, String dbUrl, String dbUser, String dbPwd) 
    PoolProperties poolProperties = new PoolProperties();
    poolProperties.setUrl(dbUrl);
    poolProperties.setDriverClassName(driverClassName);
    poolProperties.setUsername(dbUser);
    poolProperties.setPassword(dbPwd);

    poolProperties.setDefaultAutoCommit(false);
    poolProperties.setTestWhileIdle(false);
    poolProperties.setTestOnBorrow(true);
    poolProperties.setDefaultTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
    poolProperties.setValidationQuery("SELECT 1");
    poolProperties.setTestOnReturn(false);
    poolProperties.setLogAbandoned(false);
    poolProperties.setRemoveAbandoned(true);
    poolProperties.setRemoveAbandonedTimeout(20);
    poolProperties.setMaxActive(100);
    poolProperties.setInitialSize(10);
    poolProperties.setJdbcInterceptors("org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer");

    return new DataSource(poolProperties);

以及我如何获得联系:

xxx.getDataSource().getConnection();

我还没有尝试,但我的第一个电话是使用setAutoCommit(false) 直接在连接上强制自动提交。

虽然我不明白为什么poolProperties.setDefaultAutoCommit(false); 会停止工作。

堆栈跟踪:

com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Can't call rollback when autocommit=true
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
    at com.mysql.jdbc.Util.handleNewInstance(Util.java:409)
    at com.mysql.jdbc.Util.getInstance(Util.java:384)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1015)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:989)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:984)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:929)
    at com.mysql.jdbc.ConnectionImpl.rollback(ConnectionImpl.java:4805)
    at sun.reflect.GeneratedMethodAccessor302.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.apache.tomcat.jdbc.pool.ProxyConnection.invoke(ProxyConnection.java:125)
    at org.apache.tomcat.jdbc.pool.JdbcInterceptor.invoke(JdbcInterceptor.java:94)
    at org.apache.tomcat.jdbc.pool.interceptor.AbstractCreateStatementInterceptor.invoke(AbstractCreateStatementInterceptor.java:71)
    at org.apache.tomcat.jdbc.pool.JdbcInterceptor.invoke(JdbcInterceptor.java:94)
    at org.apache.tomcat.jdbc.pool.interceptor.ConnectionState.invoke(ConnectionState.java:140)
    at $Proxy333.rollback(Unknown Source)

【问题讨论】:

您能提供错误堆栈跟踪吗? 很可能是连接池或 MySQL JDBC 驱动程序中的错误。除此之外,我认为这个问题是无法回答的。 @MarkRotteveel 好吧,我没有发现任何此类错误的痕迹。但是我们将尝试直接在连接上强制属性。如果可行,它可能会对其他人有所帮助。 【参考方案1】:

这就是今天的内容,我在池创建的每个连接上强制使用AutoCommit 属性。

这行得通,所以它肯定是池类的一个错误。

编辑: 我也遇到了以相同方式设置但未考虑在内的事务隔离问题。经过一番研究,我发现这可能与我使用的 Mysql 连接器/J (http://dev.mysql.com/doc/refman/5.1/en/connector-j-reference-configuration-properties.html) 有关。

我在文档中发现了这个有趣的参数:

使用LocalSessionState

驱动程序是否应该引用 autocommit 的内部值和 Connection.setAutoCommit() 设置的事务隔离和 Connection.setTransactionIsolation() 和事务状态为 由协议维护,而不是查询数据库或 盲目地向数据库发送commit()或rollback()命令 方法调用?

默认值: false

【讨论】:

以上是关于使用连接池一段时间后自动提交更改为 TRUE的主要内容,如果未能解决你的问题,请参考以下文章

iOS *** 一段时间后自动断开连接

maven更新后Java版本自动更改为java 1.5

unity客户端自动断开连接

MariaDB 默认函数将自动增量的 PK 字段更改为 null

Mybatis中在关闭连接之前为什么要设置自动提交为true?

在 oracle 中执行存储过程后是不是发生任何自动提交?