日常Bug排查-读从库没有原子性?
日常Bug排查系列都是一些简单Bug排查。问题虽小,但经常遇到,了解这些问题,会让我们少走点弯路,提升效率。说不定有些问题你遇到过哦:)
Bug现场
业务开发同学突然问了笔者一个问题,从库读会不会没有原子性?我下意识的反应怎么可能,只要是遵守MySQL主从Replication协议的原子性至少是能够保证的。但他们遇到了一个比较诡异的现象。如下图所示:
这么一看确实像从库没有保证原子性。但这个明显有违背笔者的常识,这个问题背后肯定还有其它的因素没有挖掘到。
数据库拓扑
于是笔者看了看这个库的拓扑,是一主两从的结构。如下图所示:
真相大白
看到这个拓扑的那一刻笔者立马反应过来,是踩了一个主从延迟变种的坑。由于请求B的两条select是不在事务内的,而且都是select。这两很有可能路由到两个不同的从库,而这两个从库的主从延迟是不一样的。例如一个100ms,一个200ms。那么落到100ms从库的那条sql就会查到请求A的提交,而200ms从库的那条sql查不到。以致与错误的认为从库不保证原子性!
应该怎么做
遇到这种情况,其实我们所需要做的只是在某次请求中稳定的路由到某个特定的从库上面,这样就能保证原子性(要么能查到,要么都查不到)。
如上图所示,一般在第一次请求之后,在threadLocal中打上相关粘性标签(SlaveA),那么在这次线程请求中。后来的从库select都走SlaveA即可。这个选择逻辑可以通过重载数据源DataSource的getConnection逻辑来实现。
总结
主从延迟是个非常常见的问题。最常见的是主库写入后读从库没有相应的数据,当然也有本文描述的这种看上去”不符合原子性”的变种。看似违背常识的背后可能有其它的隐变量(多从库不同延迟)。多挖掘一点问题现场的上下文信息就很容易揪出问题的根因。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)