Spring事务管理报错:Transaction rolled back because it has been marked as rollback-only

昨天一个应用了很久的功能突然报错500,追踪日志后发现是Spring的事务管理报了错

Transaction rolled back because it has been marked as rollback-only

报错信息是:”Transaction rolled back because it has been marked as rollback-only“

字面意思翻译就是:事务回滚了,因为它被标记为必须回滚

要想理解这句话就必须先知道 Spring 事务管理的一种传播属性: 嵌套事务

顾名思义 嵌套事务 就是 A B 两个事务,B 事务作为一个 A 的内部事务,如果 B事务失败则会给外层事务也就是 A 事务一个标记,标记 A 事务也必须回滚,否则会导致数据不一致

知道了什么是嵌套事务后我们再来理解这句话,意思就是 内层事务报了错,影响到了外层事务,所以只需要进入内部方法查看报错信息即可,由于代码比较久远质量比较差,代码没有打印错误信息,尝试自己调用却无法复现事务报错,这是为什么?

是因为 Spring 事务是基于代理的方式去做,自己手动调方法自然是行不通的。

继续深入内层,最后将报错原因锁定在了数据库外键约束处理上

报了如下错误:

Cannot add or update a child row: a foreign key constraint fails (`client_group`, CONSTRAINT `fk_client_id` FOREIGN KEY (`client_id`) REFERENCES `client_old` (`client_id`)

是一个外键约束报错,表结构如下:

----- group 群组表

----- client 用户表

----- client_group 关联表

关联表设置了两个外键,分别是 client_id 和 group_id,如果两个外键没有从对应的 client 、group表找到合适的 id 范围,就会报错

但是由于前不久其他的开发更新了数据库,将原先的 client 表拷贝了一个新表,旧表就改为了没有数据的 client_old 表,但是由于外键没有更新,存储的仍然是 client_old 表的 id,所以引发了数据报错,这种情况就需要我们去更新一下外键,让它和 新表建立联系即可。

更新外键操作如下:

首先需要 禁止外键约束,否则无法新增更改外键

SET FOREIGN_KEY_CHECKS=0

再删除之前的外键

alter table client_group drop foreign key fk_client_id;

在插入一个外键

alter table results add constraint fk_client_id foreign key(client_id) references client(client_id);

最后不要忘记将外键约束打开哦!

SET FOREIGN_KEY_CHECKS=1

 至此 bug 修复完毕,系统可以正常的运行,经过这一次修复,我的知识库得以扩充,很多一起书本上生冷的知识瞬间变得活化火热进入我的大脑;也提醒了我们线上数据库的修改一定要谨小慎微,任何一个改动都可能导致之前积压的设计崩塌。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值