先啰嗦一下:使用的spring的事务代理,有一条策略是:PROPAGATION_REQUIRES_NEW
需要事务处理。并总是开启一个新事务。如果已经存在事务环境,则挂起之
简单来说就是使用了这个策略就是每次都会强起一个新事务。这个在保证一些必须要提交的业务逻辑上比较常用(不管外部调用是否有事务的环境,也不管外部调用环境是否发生了异常),比如,说保存日志等。
遇到的问题如下:
问题现象:
1,使用PROPAGATION_REQUIRED事务策略之后使用了PROPAGATION_REQUIRES_NEW事务策略(在此策略中执行delete语句),导致系统卡死,
2,在某些情况下执行PROPAGATION_REQUIRES_NEW事务策略(在此策略中执行update语句),抛错误:(不是每次都能出现)
Hibernate-related JDBC operation; SQL []; The current transaction has been rolled back because of a deadlock or timeout. Reason code "2".. SQLCODE=-911,
SQLSTATE=40001, DRIVER=3.58.81; nested exception is com.ibm.db2.jcc.am.to: The current transaction has been rolled back because of a deadlock or timeout. Reason
code "2".. SQLCODE=-911, SQLSTATE=40001, DRIVER=3.58.81
同样的代码在weblogic+db2就没有问题。
问题分析:
整个过程是这样的:
从客户端发起请求--->服务端service层响应--->hibernate生成持久化的请求
--->中间件获取连接提交jdbc请求(包括事务控制)--->db驱动提交请求到数据库
既然weblogic+db2没有问题,was+db2有问题,整个过程只有在中间件这块不一样,所以怀疑的重点就是was,一定是was对这样的业务场景的事务没有处理好。尤其是was对spring的PROPAGATION_REQUIRES_NEW事务策略支持很值得怀疑。
http://www.xuehuile.com/blog/1af3ad9c92624ff7abbf66e289f5df3c.html
虽然我不了解spring的PROPAGATION_REQUIRES_NEW事务策略是怎么实现的。由于能力有限看了代码也没有看明白。但是问题还是要解决,所以只能死磕重点嫌疑犯was上。现象分析应该是锁表了,db2的默认级别也是CS,但是问题出现的时候,貌似将事务的隔离级别提高了,由行级索提高到对所有的结果集加锁,经分析,是因为死锁或超时导致执行不成功,怀疑和WAS数据源的隔离级别有关系。后来发现was里面应用的数据源的事务相关的属性webSphereDefaultIsolationLevel的值是空的,这个也可能是此时隔离级别为啥提高的原因吧,因为中间件就没有设置隔离界别。
解决方法:
1.登录到was控制台,
2.在左侧树中依次选择 资源--JDBC--数据源
3.点击右侧的 定制属性 连接
在名称列填 webSphereDefaultIsolationLevel,值列参照下表填写(解决锁冲突可填写值2,CS隔离级别)
后记:也有一种方案是设置数据库的隔离界别,因为db2发现数据库的隔离级别也是空的,应该改成CS,但是我觉得不应该轻易的去改变数据库的隔离界别(至少在我没有成为一个DB高手之前),因为问题你的应用的代码在某些组合逻辑下就会报这样的问题。所以改动这个应用的某些配置使得问题得到解决是合理的。
http://blog.itpub.net/8484829/viewspace-476751