读写分离导致读不到刚插入的数据

背景

前两天在做一个功能的时候,需要先插表,如果数据重复则从数据库中查询出这条数据,这段代码在测试环境并没有什么问题,但是到生产之后就会偶现的报一些错,就是读不到已插入的数据,导致后续业务出现问题。

问题排查

查询日志发现,插入是成功的,显示update的条数为1,但是紧跟着的查询却显示total为0,这意味着没有查询到那条数据,于是排查了一下查询条件,也没有什么问题。

利用先进生产力

​ 最开始想的是会不会是因为事务的提交问题,因为从提交事务到数据入库,中间有没有可能有一个时间差,导致数据没有查询到,于是尝试着在CahtGpt和文心一言上查询了一下,得到如下答案

CahtGpt:

读写分离导致读不到刚插入的数据_第1张图片
读写分离导致读不到刚插入的数据_第2张图片
读写分离导致读不到刚插入的数据_第3张图片
读写分离导致读不到刚插入的数据_第4张图片

读写分离导致读不到刚插入的数据_第5张图片
读写分离导致读不到刚插入的数据_第6张图片

读写分离导致读不到刚插入的数据_第7张图片

文心一言:

读写分离导致读不到刚插入的数据_第8张图片

读写分离导致读不到刚插入的数据_第9张图片

读写分离导致读不到刚插入的数据_第10张图片

可以发现在这几个问题的回答上ChatGpt要比文心一言要强上很多,这样一比文心一言依旧是人工智障的水平

排除事务的可能性

根据ChatGpt的描述 ,如果使用了异步事务是可能会出现事务提交后再查询就查询不出来的情况,或者使用了try catch,

ChatGpt给出的建议是

  1. 将查询方法和写方法并入到一个事务中,这样就可以保证能查询的出来。不过将查询语句方法放入整体事务会影响事务的效率。
  2. 修改事务的隔离级别,Mysql默认的事务隔离级别是读已提交,如果我把这个写事务的隔离级别修改为读未提交,则可以读取到数据。不过这种方法很明显不符合常理,也会产生脏读、幻读、不可重复读等问题

不过这些情况都不符合我的实际情况,我没有使用异步事务,也没有进行try catch,因此不是这些原因导致的。事务是肯定提交了的,于是我思索了很久,突然想到了我们的数据库是做了读写分离的

找到问题

我们的数据库使用的是阿里的PolarDB集群。默认是做了读写分离的,因此我怀疑是在数据写入写库的时候,还没来得及同步到读库,我就快速的去查询了读库,导致没有读取到那条数据,于是我翻阅了一下阿里云的 云原生数据库 PolarDB MySQL版 的文档,发现了一些端倪

读写分离导致读不到刚插入的数据_第11张图片

官方文档上就对读不到刚插入的数据这一情况做了专门的解释,就是根据一致性级别的配置不同,不一定保证能够马上读到刚插入的数据。

而官方也列举了解决方案,即在读SQL前加上/* FORCE_MASTER */来让这个读操作强行走写库,这样的话就能查询到刚插入的数据,如下

请添加图片描述

我也询问了DBA,DBA也验证了我所说的情况是存在的

  • 最好的方式是在查询的sql前面加 /* FORCE_MASTER */ 让它路由到只查询主库
  • 如果插入与查询是写在一个事务里面的:先insert 后再去select 的话就不用加强制路由
  • 如果这个事务是先select再insert的话,这个事务在mysql这边会进行事务拆分,先select的查询会走到只读实例,其他后面的dml操作会走到主节点

结论

这次问题就是因为读写分离导致的读不到刚插入的数据,所以直接让读操作强行去写库读取数据就可以避免读取不到的问题

你可能感兴趣的:(数据库,sql,mysql,transactional,读写分离)