如何让AI生成自己喜欢的歌曲-AI音乐创作的正确方式 - 第507篇
ES 深度分页问题及针对不同需求下的解决方案[ES系列] - 第509篇
抖音主播/电商人员有福了,利用Suno创作产品宣传,让产品动起来-小米Su7 - 第510篇
Spring Boot整合ElasticSearch实战 - 第511篇
悟纤:师傅,最近做一个项目,碰到了事务问题,我感觉代码写的也没啥问题呢?
师傅:没啥问题,怎么会报错?幸亏框架给你报错了,不然上线了要被打屁屁。
悟纤:师傅,又嘲笑我~ 😭
师傅:徒儿,你这个都是小问题,是不是最近偷懒了,没好好学习,要时刻保持学习的状态,活到老,学到老,终身学习,这些要刻在脑里。
悟纤:师傅说的极是,现在AI这么火,每个人都会有点焦虑,害怕被时代说淘汰。
师傅:话不多了,让为师给你瞅瞅是什么问题?
师傅:这不是Transaction rolled back because it has been marked as rollback-only,这个很好解决,最常见的情况就是一个事务因为异常回滚了,另外一个事务捕捉了异常,却没有再向上抛出而引起的。
悟纤:那师傅,赶紧和徒儿说说呗~
导读
最近在开发一个AI导航项目(地址在下面)的时候,遇到了Transaction rolled back because it has been marked as rollback-only这个异常,没想到写了10多年的代码,还写出了事务异常。
项目地址:http://ai.dzwlai.com/
AI导航站,汇总800+工具集合:
分析
这个异常“Transaction rolled back because it has been marked as rollback-only”通常出现在事务管理中,表明某个事务已被标记为仅回滚,因此无法正常提交,只能回滚。这个标记通常是由于事务中发生了一些导致无法继续进行的错误或异常情况。下面是一些可能导致事务被标记为rollback-only的常见原因:
(1)业务逻辑错误:在事务执行过程中,如果业务逻辑检测到某些条件不满足,可能会主动标记事务为rollback-only,以防止数据不一致。
(2)异常处理:在事务中捕获到异常后,如果没有正确处理(如捕获异常后继续执行而不是终止事务),事务管理器可能会将事务标记为仅可回滚状态。
(3)资源失败:如数据库连接中断、SQL错误等资源问题也可能导致事务回滚。
(4)超时:事务执行时间过长超过预设的超时限制时,事务管理器可能会自动将事务标记为rollback-only。
(5)嵌套事务问题:在嵌套事务中,如果内部事务被标记为rollback-only,它可能会影响到外围事务。
博主遇到的情况
在这里后端使用的Spring Boot的框架:
其实原因就是嵌套事务导致的,因为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方法继续使用该事务,然后又执行事务提交的操作,所以最后会抛异常)
示例
public void saveUser() {
try {
SysUser user = new SysUser();
user.setUserName("wuqian");
//这里做了保存操作
this.save(user);
//这里调用了saveRole方法,是另外一个service的
roleService.saveRole();
//执行完提交事务
}catch (Exception e ){
//a方法catch了异常但是没有继续抛出,事务会提交
e.printStackTrace();
}
}
//roleService的saveRole()
public void saveRole() throws Exception {
//b方法抛出异常
throw new Exception("Exception");
}
上面的例子总,有saveUser和saveRole两个方法,这两个方法都开启了事务,saveUser方法中调用saveRole方法(因为都使用事务,默认的事务传播级别是PROPAGATION_REQUIRED,所以这过程中会使用同一个事务);
当执行saveRole方法的时候,saveRole方法抛出异常,这个时候事务就会被标记为仅回滚(因为在saveRole方法中抛出异常,saveRole方法这事务本该是要回滚,所以会将saveRole方法的事务标记为rollback-only);
但是在saveUser方法又catch到saveRole方法抛的异常,但是A方法catch到异常后没有继续往上抛出,而是继续执行后面的代码,最后正常提交事务,那么就会抛出 Transaction rolled back because it has been marked as rollback-only这异常!