一、引言
最近有人用博主的Redis回滚工具的时候提出了一个问题,这个工具是根据事务过程中的异常进行回滚,从而保证DB与redis的一致性。
那么如果在事务提交的时候Mysql成功了,但是Spring以为没有成功抛出异常,这时候redis回滚工具失效,那么不就变成了mysql有数据,redis没有了吗?
这位同学明显对于spring和mysql的事务交互还不是那么理解。
二、分析
1、首先我们看一下他以为的问题是如何发生的,他自己对这个问题的过程可能都不是很清晰,问他怎么会mysql完成了spring不知道抛出异常,他明显有点蒙,但是图一画就比较清晰了,少了一个步骤
2、少的一个步骤就是mysql执行完成应该给spring一个响应包,如果在网络过程中丢失,那么spring就会自检超出时间然后抛出“java.sql.SQLTimeoutException”,但是他认为的是spring抛出这个异常之后,mysql事务已经完成了,所以不会回滚了。
3、这里就要提到spring事务到底是怎么跟mysql交互的,在《Mysql技术内幕:Innodb存储引擎》当中,开启事务之后的回滚其实是利用mysql自带的保存点技术,相当于持有一个标记,在需要的时候回滚到这个标记所在的数据镜像,而数据镜像保存在undo log当中
4、事务提交之后,扁平事务仍然可以回滚到任意一个保存点,链事务其实就跟spring注解中的广播模式比较相关了,根据原理想想它的设置其实很简单,这里不多做描述了
5、回到最初的问题,会出现Mysql提交之后Spring以为没有成功吗,答案是会,但是会出现spring抛出异常之后,mysql由于已经提交事务就不回滚吗,答案是否,仍然可以由保存点进行回滚,所以不存在这位同学说的问题。
四、总结
考虑异常情况要结合很多原理,这样才知道会不会发生,这里主要是对spring框架和《Mysql技术内幕:Innodb存储引擎》的理解与分析,当然也不代表博主的分析完全正确,有不同意见欢迎评论区沟通。