Transaction rolled back because it has been marked as rollback-only
现象
日志里提示了如下一个错误:Transaction rolled back because it has been marked as rollback
意思是,准备提交事务,将落地的数据库数据生效时,事务已经被设置为rollback-only了,无法提交事务。后面仔细看了一下代码,原来是开了事务的方法里,抛了一个异常,但是程序把这个异常给catch住了,没往上抛。
原因
字面上的意思就是:事务已回滚,因为它已被标记为仅回滚,那为什么会标记为仅回滚呢?
其实原因就是嵌套事务导致的,因为spring事务有传递性,spring默认的事务传播级别是PROPAGATION_REQUIRED,即当前上下文存在事务则用此事务,如果不存在事务则新建一个事务执行;
那么现在有A和B两个方法,这两个方法都开启了事务,A方法中调用B方法(因为都使用事务,默认的事务传播级别是PROPAGATION_REQUIRED,所以这过程中会使用同一个事务);
当执行B方法的时候,B方法抛出异常,这个时候事务就会被标记为仅回滚(因为在B方法中抛出异常,B方法这事务本该是要回滚,所以会将B方法的事务标记为rollback-only);
但是在A方法又catch到B方法抛的异常,但是A方法catch到异常后没有继续往上抛出,而是继续执行后面的代码,最后正常提交事务,那么就会抛出 Transaction rolled back because it has been marked as rollback-only这异常!(因为AB是用同一个事务,在B方法执行的时候这个事务就标记为rollback-only,然后A方法继续使用该事务,然后又执行事务提交的操作,所以最后会抛异常)
1 |
|
1 |
|
解决办法
1、在B方法中进行try case case中不进行抛错处理;
2、在A方法case中继续抛错处理;
3、在B方法上的Transaction 添加事务传播规则为 propagation = Propagation.REQUIRES_NEW 新建事务进行处理