上来先抛出两个工作中遇到的问题,1:在业务场景中,写过这么一段代码,先更新数据库,然后在代码下面在读取(注意,两块代码不在同一个service上,第一个更新操作service已有事务注解,第二个没有),结果发现读取到的值与写入的值不一致,读取到的是老值。2:一次手残,使用navicate连接数据库时候连接到从库上了,使用navicate更新数据,结果发现在代码service层(已经加了事务注解)读取的值还是未更新之前的值。数据库代理是MySQL Proxy。
这两个问题是不同时间段发生的,第一个问题是在实习的时候发生的,然后当时没有弄明白,只知道主数据库写入值了,读值是在从库上读取的,中间会有一个很短的时间差,已经写入了主数据库但是还没有写入到从数据库上,这个时间差很短,但是如果我们在程序中执行的话,就会经常遇到这种bug了,当时不懂,解决方案是在程序中强制性暂停100毫秒后在读取。
第二个问题当时也是查了好长时间,发现自己连到从库上了,导致主数据库没有更新,所以读取的时候读取的是主库上的值(即老值)
仔细琢磨了下感觉很有意思的事情发生了,第二次我也是读取操作,为什么就读取到了主库上的值,莫非是加注解的问题,加了注解会导致读取主库上的数据,没加注解的时候会读取从库上的数据。查阅资料后发现,
资料来源:https://frank1998819.iteye.com/blog/1928284
看到没,如果我们使用事务之后,所有的事务操作(在同一个事务之内的操作)是放在master库执行的,并且事务之内不改变连接(代表如果有多个master库的话也会在同一个master库上执行完所有的操作)
恍然大悟,最后小小建议:在同一次请求中写操作之后所有对数据库的操作都放在事务内进行,当然,如果最前的几步操作都是读取操作,放不放无所谓,但是读取操作如果在写操作之后,一定一定开启事务在事务之内操作