Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在数据库测试连接查询中事务已启动但未结束_Java_Spring_Postgresql_Groovy_Bonecp - Fatal编程技术网

Java 在数据库测试连接查询中事务已启动但未结束

Java 在数据库测试连接查询中事务已启动但未结束,java,spring,postgresql,groovy,bonecp,Java,Spring,Postgresql,Groovy,Bonecp,最近,我们的应用程序中发现了一个bug,它导致操作时间与实际时间不同。我们正在使用当前的\u timestamp PostgreSQL函数,而不是从代码中传递时间。我们调查了一下,发现问题与一些正在开始但从未结束的事务有关 该应用程序使用Spring的DataSourceTransactionManager,它完美地完成了每一个事务操作。现在,问题似乎来自我们的连接池libBoneCP。我们已配置SELECT 1查询以检查数据库连接。PostgreSQL日志中实际显示的内容如下: LOG: ex

最近,我们的应用程序中发现了一个bug,它导致操作时间与实际时间不同。我们正在使用当前的\u timestamp PostgreSQL函数,而不是从代码中传递时间。我们调查了一下,发现问题与一些正在开始但从未结束的事务有关

该应用程序使用Spring的DataSourceTransactionManager,它完美地完成了每一个事务操作。现在,问题似乎来自我们的连接池libBoneCP。我们已配置SELECT 1查询以检查数据库连接。PostgreSQL日志中实际显示的内容如下:

LOG: execute S_1: BEGIN
LOG: execute <unnamed>: SELECT 1
LOG: execute S_1: BEGIN
LOG: execute <unnamed>: SELECT 1
在任何连接测试语句之后都没有提交。进一步的日志显示在选择1之前没有更多的BEGIN命令,但我猜这是因为当一个连接已经处于活动状态时,该连接无法启动新事务

我想知道这是否是一些错误或什么可能是错误的

以下是servlet上下文配置部分文件,仅发布相关部分:

<bean id="ds" class="com.jolbox.bonecp.BoneCPDataSource" destroy-method="close">
    <property name="idleConnectionTestPeriodInMinutes" value="5"/>
    <property name="idleMaxAgeInMinutes" value="30"/>
    <property name="lazyInit" value="true"/>
    <property name="maxConnectionsPerPartition" value="95"/>
    <property name="minConnectionsPerPartition" value="1"/>
    <property name="partitionCount" value="3"/>
    <property name="acquireIncrement" value="5"/>
    <property name="statementsCacheSize" value="100"/>
    <property name="releaseHelperThreads" value="3"/>
    <property name="defaultAutoCommit" value="false"/>
    <property name="connectionTestStatement" value="SELECT 1;"/>
</bean>

<bean id="sql" class="groovy.sql.Sql">
    <constructor-arg ref="dsProxy"/>
</bean>

<tx:annotation-driven transaction-manager="txManager" proxy-target-class="true"/>

<bean id="dsProxy" class="org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy">
    <constructor-arg ref="fooDSProxy"/>
</bean>

<bean id="fooDSProxy" class="org.something.Foo" factory-method="createProxy">
    <constructor-arg ref="ds"/>
</bean>

<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dsProxy"/>
</bean>
其中org.something.Foo没有任何特殊功能,用于日志记录


感谢您的帮助。

此问题可能是由于数据库连接上的自动提交设置造成的

顾名思义,autocommit会自动将每个SQL语句包装在自己的事务中,并在语句完成时隐式提交该事务。对于许多生产场景,自动提交没有意义;您通常希望将一批SQL操作组合到一个事务中,然后提交或回滚工作单元

数据库连接池设置显式关闭连接上的自动提交,因此我建议在没有显式提交的事务中执行SELECT 1 connection test语句。这将解释为什么您看到BEGIN语句,然后没有commit。解决此问题的方法是更新连接测试语句,以包含显式事务划分,例如,在语句中添加BEGIN和COMMIT

至于那些未提交的连接的实际情况,这将取决于实际的数据库实现本身。也许值得一读的是什么 PostgreSQL在这里就可以了


Hibernate文档解释了依赖自动提交的情况。绝对值得一读。

猜测一下,connectionTestStatement查询正在与自动提交设置为false的连接一起使用。假设您的测试语句中没有明确的事务边界,DB可能会回滚事务,而不是提交它,或者只是让它挂起。也许可以尝试将显式事务启动和提交添加到您的连接测试语句中?Rob建议,一种可能的解决方案是将提交添加到测试连接语句中,它可以工作,我已经测试了至少一个bug消失,PostgreSQL日志报告了事务的结束。但问题依然存在:——|。从哪里开始?执行测试查询时是否触发TransactionManager?如果它被触发,为什么在这种特殊情况下它没有检测到事务的结束?据我所知,不可能在没有事务的情况下从DB读取数据,因此您总是看到BEGIN语句。自动提交意味着事务将始终被提交,但如果您关闭自动提交,那么所有关于事务发生什么以及何时发生的赌注都将被关闭。这在不同的DB实现之间会有所不同。Java持久化与Hibernate的书中有这样一句话,这是非常有用的:基本上,这可能来自驱动程序本身?维基上写的东西很有意义。。但这可能是BoneCP的一个缺陷,因为即使使用默认的测试连接查询,它从数据库中获取一些元数据,并且比simple select 1慢得多,也无法完成事务。。我建议你把你的评论整理成一个答案,我很乐意接受。