最近在我们的应用程序中发现了一个错误,导致操作时间与实际时间不同(我们使用的是current_timestamp()PostgreSQL函数,而不是从代码中传递时间)。我们已经对它进行了调查,发现问题不得不与一些已经开始但从未结束的交易有关。
该应用程序使用Spring DataSourceTransactionManager
,它可以完美地完成工作(每个事务操作都按预期结束)。现在,问题似乎来自我们的连接池lib(BoneCP)。我们已配置SELECT 1
查询以检查数据库连接。 PostgreSQL日志中实际显示的内容如下:
LOG: execute S_1: BEGIN
LOG: execute <unnamed>: SELECT 1
LOG: execute S_1: BEGIN
LOG: execute <unnamed>: SELECT 1
没有COMMIT跟随任何连接测试语句(进一步的日志显示在SELECT 1之前没有更多BEGIN命令,但我想这是因为当一个已经激活时,该连接无法启动新事务。
我想知道是不是有些错误或可能出错?
这是servlet-context配置文件(仅发布相关部分):
<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
没有什么特别之处,用于记录目的。
任何帮助表示感谢。
答案 0 :(得分:0)
问题可能是由于数据库连接上的自动提交设置。
正如名称所暗示的那样,autocommit会自动将每个SQL语句包装在自己的事务中,并在语句结束时隐式提交该事务。对于很多生产场景,自动提交没有意义;您通常希望将一批SQL操作组合到一个事务中,然后提交或回滚工作单元。
您的数据库连接池设置显式关闭了连接上的自动提交,因此我建议您在没有显式提交的事务中执行您的SELECT 1
连接测试语句。这可以解释为什么你看到BEGIN
语句然后没有提交。解决此问题的方法是更新连接测试语句以包括显式事务划分,例如在语句中添加BEGIN
和COMMIT
。
就未提交的连接实际发生的情况而言,这将取决于实际的数据库实现本身。可能值得一读的是什么 PostgreSQL会在这里做。
Hibernate文档提供了pretty good对依赖自动提交的情况的解释。绝对值得一读。