日常Bug排查-读从库没有原子性?

日常,bug,排查,没有,原子 · 浏览次数 : 9

小编点评

**日常Bug排查系列中遇到原子性问题的原因:** 1. **主从延迟变种**:当请求B的两条select不在事务内,它们可能会路由到不同的从库。由于两个从库的主从延迟可能不同,这会导致落到不同的库时,导致原子性失效。 2. **多从库不同延迟**:即使请求在同一事务中,多个从库也可能拥有不同的延迟。这也会导致部分请求路由到不同的库,从而导致原子性失效。 3. **线程局部变量**:在第一次请求之后,在threadLocal中打上相关粘性标签(SlaveA)后,后续从库select都走SlaveA即可。由于 threadLocal是单线程的,这会导致某些请求被路由到不同的库,从而导致原子性失效。 4. **数据源选择**:在重载数据源DataSource的getConnection逻辑中,设置了多个数据源,这会导致多个连接同时打开。由于每个连接对应一个从库,这会导致原子性失效。 5. **多数据库连接**:如果数据库配置了多个数据库连接,这也会导致原子性问题。因为每个连接对应一个从库,当多个连接访问同一个表时,可能会出现多个请求在同一时刻路由到不同的库,导致原子性失效。

正文

日常Bug排查系列都是一些简单Bug排查。问题虽小,但经常遇到,了解这些问题,会让我们少走点弯路,提升效率。说不定有些问题你遇到过哦:)

Bug现场

业务开发同学突然问了笔者一个问题,从库读会不会没有原子性?我下意识的反应怎么可能,只要是遵守MySQL主从Replication协议的原子性至少是能够保证的。但他们遇到了一个比较诡异的现象。如下图所示:

 

 

这么一看确实像从库没有保证原子性。但这个明显有违背笔者的常识,这个问题背后肯定还有其它的因素没有挖掘到。

数据库拓扑

于是笔者看了看这个库的拓扑,是一主两从的结构。如下图所示:

 

 

真相大白

看到这个拓扑的那一刻笔者立马反应过来,是踩了一个主从延迟变种的坑。由于请求B的两条select是不在事务内的,而且都是select。这两很有可能路由到两个不同的从库,而这两个从库的主从延迟是不一样的。例如一个100ms,一个200ms。那么落到100ms从库的那条sql就会查到请求A的提交,而200ms从库的那条sql查不到。以致与错误的认为从库不保证原子性!

 

 

应该怎么做

遇到这种情况,其实我们所需要做的只是在某次请求中稳定的路由到某个特定的从库上面,这样就能保证原子性(要么能查到,要么都查不到)。

 

 

如上图所示,一般在第一次请求之后,在threadLocal中打上相关粘性标签(SlaveA),那么在这次线程请求中。后来的从库select都走SlaveA即可。这个选择逻辑可以通过重载数据源DataSource的getConnection逻辑来实现。

总结

主从延迟是个非常常见的问题。最常见的是主库写入后读从库没有相应的数据,当然也有本文描述的这种看上去”不符合原子性”的变种。看似违背常识的背后可能有其它的隐变量(多从库不同延迟)。多挖掘一点问题现场的上下文信息就很容易揪出问题的根因。

 

与日常Bug排查-读从库没有原子性?相似的内容:

日常Bug排查-读从库没有原子性?

日常Bug排查系列都是一些简单Bug排查。问题虽小,但经常遇到,了解这些问题,会让我们少走点弯路,提升效率。说不定有些问题你遇到过哦:) Bug现场 业务开发同学突然问了笔者一个问题,从库读会不会没有原子性?我下意识的反应怎么可能,只要是遵守MySQL主从Replication协议的原子性至少是能够

如何实现简单的分布式链路功能?

为什么需要链路跟踪 为什么需要链路跟踪?微服务环境下,服务之间相互调用,可能存在 A->B->C->D->C 这种复杂的服务交互,那么需要一种方法可以将一次请求链路完整记录下来,否则排查问题不好下手、请求日志也无法完整串起来。 如何实现链路跟踪 假设我们从用户请求接口开始,每次请求需要有唯一的请求

日常Bug排查-改表时读数据不一致

前言 日常Bug排查系列都是一些简单Bug的排查。笔者将在这里介绍一些排查Bug的简单技巧,同时顺便积累素材。 Bug现场 线上连续两天出现NP异常,而且都是凌晨低峰期才出现,在凌晨的流量远没有白天高峰期大。而出问题的接口又是通常的业务请求。于是,很自然的,我们就想凌晨有什么特殊的运维动作,翻了下时

日常Bug排查-MVCC和for update混用导致读数据不一致

日常Bug排查-MVCC和for update混用导致读数据不一致 前言 日常Bug排查系列都是一些简单Bug的排查。笔者将在这里介绍一些排查Bug的简单技巧,同时顺便积累素材。 Bug现场 又是喜闻乐见的读数据不一致的问题。这次的问题是这样,业务在一个事务中更新A和B两个表的两个数据。但是在另一个

日常Bug排查-偶发性读数据不一致

日常Bug排查-偶发性读数据不一致 前言 日常Bug排查系列都是一些简单Bug的排查。笔者将在这里介绍一些排查Bug的简单技巧,同时顺便积累素材。 Bug现场 业务场景 先描述这个问题出现的业务场景。这是一个支付的场景,如果支付成功了,我们就把支付状态置为success(主单据更新)同时写入支付成功

日常Bug排查-连接突然全部关闭

日常Bug排查-连接突然全部关闭 前言 日常Bug排查系列都是一些简单Bug的排查。笔者将在这里介绍一些排查Bug的简单技巧,同时顺便积累素材。 Bug现场 最近碰到一个问题,一台机器上的连接数在达到一定连接数(大概4.5W)连接数之后会突然急速下降到几百。在应用上的表现就是大量的连接报错,系统失去

debug技巧之远程调试

一、前言 大家好啊,我是summo,今天给大家分享一下我平时是怎么调试代码的,不是权威也不是教学,就是简单分享一下,如果大家还有更好的调试方式也可以多多交流哦。 当我们的应用发布到线上之后,就不能随意启停了,但如果线上出现了BUG怎么办呢?大多数时候我们会借助线上打印的日志进行排查问题,如果幸运的话

《最新出炉》系列入门篇-Python+Playwright自动化测试-42-强大的可视化追踪利器Trace Viewer

1.简介 在我们日常执行自动化测试工作的过程中,经常会遇到一些偶发性的bug,但是因为bug是偶发性的,我们不一定每次执行都能复现,所以我们在测试执行的时候,追踪用例执行就变得非常重要了。playwright提供了一个Playwright Trace Viewer工具来追踪测试执行,这是一个GUI工

FastJson不成想还有个版本2啊:序列化大字符串报错

# 背景 发现陷入了一个怪圈,写文章的话,感觉只有大bug或比较值得写的内容才会写,每次一写就是几千字,争取写得透彻一些,但这样,我也挺费时间,读者也未必有这么多时间看。 我想着,日常遇到的小bug、平时工作中的一些小的心得体会,都还是可以写写,这样也才是最贴近咱们作为一线开发生活的,也不必非得是个

测试的底层逻辑

写这篇文章,是希望把我的一些我认为是非常有价值的经验总结出来,能够帮助刚做测试不久的新同事,或者是测试经验丰富的老同事以共享。希望我们可爱的新同事,准备要在测试领域耕耘的伙伴,能够通过我的文章了解到测试的底层逻辑,也就是我们测试工作中可能看不到隐藏较深的点,而不只是日常所见的写用例、提bug、开发自动化、做平台;俗话说外行看热闹,内行看门道。