问题背景:
项目组在使用Spring事务时,通过编程式事务的形式,手动在业务代码中注入DataSourceTransactionManager,创建DefaultTransactionDefinition后开启事务,等待业务代码处理完成后再手动进行commit or rollback。
正常使用的时候没有问题,但是由于项目组成员较多,部分粗心的组员在使用编程式事务时,会忘记提交或者在事务提交之前就return了,导致事务挂起,业务高并发下甚至产生连接池占满,新业务无法获取到数据库连接的情况,导致生产事故。
为了避免组员忘记关闭事务,我对编程式事务的开启做了一定的封装,并且在事务开始后,声明一个Timer计时器,约定计时器结束时如果事务没有关闭,则将事务强制进行回滚。这样一定程度上防止了事务忘记关闭的问题,当程序员发现业务数据经常被回滚时,就可能注意到是他忘了提交事务,数据库的连接也得到了释放。
通过计时器已经实现了上述功能,但是出现了一个问题。计时器相当于开启了一个子线程,我将事务传递到子线程中,计时器触发后,在子线程中进行了事务回滚。之后回到主线程,如果此时我希望登记一条系统错误日志在数据库中,在插入日志表时,主线程数据库就会报错Cause: java.sql.SQLException: connection closed。经过多次调试,发现确实是子线程完成强制回滚后,主线程的数据库连接就会断开,导致我的日志无法插入。
在网上搜了一些资料,无法解决该问题。部分代码我截图粘在楼下
项目组在使用Spring事务时,通过编程式事务的形式,手动在业务代码中注入DataSourceTransactionManager,创建DefaultTransactionDefinition后开启事务,等待业务代码处理完成后再手动进行commit or rollback。
正常使用的时候没有问题,但是由于项目组成员较多,部分粗心的组员在使用编程式事务时,会忘记提交或者在事务提交之前就return了,导致事务挂起,业务高并发下甚至产生连接池占满,新业务无法获取到数据库连接的情况,导致生产事故。
为了避免组员忘记关闭事务,我对编程式事务的开启做了一定的封装,并且在事务开始后,声明一个Timer计时器,约定计时器结束时如果事务没有关闭,则将事务强制进行回滚。这样一定程度上防止了事务忘记关闭的问题,当程序员发现业务数据经常被回滚时,就可能注意到是他忘了提交事务,数据库的连接也得到了释放。
通过计时器已经实现了上述功能,但是出现了一个问题。计时器相当于开启了一个子线程,我将事务传递到子线程中,计时器触发后,在子线程中进行了事务回滚。之后回到主线程,如果此时我希望登记一条系统错误日志在数据库中,在插入日志表时,主线程数据库就会报错Cause: java.sql.SQLException: connection closed。经过多次调试,发现确实是子线程完成强制回滚后,主线程的数据库连接就会断开,导致我的日志无法插入。
在网上搜了一些资料,无法解决该问题。部分代码我截图粘在楼下