本文正在参与「技能专题19期 闲谈数据库技能」活动

歪歪剧本杀-悬疑推理风,剧情纯属虚构

欢迎重视大众号「架构染色」交流和学习

本篇测验悬疑推理风剧本杀,剧情纯属虚构(若有雷同实属偶然):运用 A 更新了 MySQL 数据 -> canal 监听 binlog ,发给 MQ -> 运用 B 消费 MQ,并向 A 建议 Dubbo 恳求 -> 运用 A 处理时却查到了更新前的数据。这个状况多数人都没遇到过,但提前了解并躲避是必要的。

本剧本杀分上下两章:

  • 首章:《刚更新的数据竟然查不到,MySQL你到底在做什么妖-上》(本篇)
  • 终章:《刚更新的数据竟然查不到,MySQL你到底在做什么妖-下》

剧本

因剧情所需,剧本显现你在技能部门负责链路追寻体系和数据库中间件等,剧情为你日常作业中的一次排障阅历…

刚看这么多,导演大喊:男主请就位… 预备 ! Action!

你:哇喔,我这就开端演了?

一、问题首现

记住那是一个风和日丽的下午…忽然你被拉到一个临时作业群里,只见窗口中快速弹出一条音讯:@老张 binlog 中的字段更新,读 db 时却读不到。记住作为男主的你在剧本的这个章节里叫老张,看到这个音讯后,你的大脑便开端拆解这些关键字:

  1. 运用 A 将 MySQL 中 x 记载中的 y 字段更新了
  2. canal(canal 是啥,下边有介绍)监听 DB 中订单记载改变事情,发到 MQ
  3. 运用 B 消费这个 MQ, 收到这个音讯后,从 MySQL 中查询这个 x 记载
  4. 但是!!!没读到 y 字段更新后的值

一起,在你大脑的另一个区域也勾勒出如下数据流通的画面:

刚更新的数据居然查不到,MySQL你到底在做什么妖-上

对此问题有了开端画像后,你的大脑中条件反应式的冒出了一连串问题,赶紧在群里宣布:

  1. 有严峻的事务影响嘛?
  2. 最近体系有改变嘛?
  3. 这是单个记载现象嘛?
  4. 曾经发生过嘛?
  5. traceId 是什么?

得到的回复是:

  1. 问题不严峻
  2. 最近没改变
  3. 这是单个记载现象
  4. 曾经好像没遇到过
  5. 还没有接入 SkyWalking(SkyWalking 是啥,下边会介绍),现有的日志里也都看不出什么猫腻

看完前 4 个答复后得知没有严峻影响,你松了一口气,严重的心情缓和了下来;但一起也意识到没有直观的链路追寻数据,要理清楚这个问题就有点麻烦了。

1.1 canal 常识弥补:

官方这么介绍:canal [k’nl] ,译意为水道/管道/沟渠,主要用途是根据 MySQL 数据库增量日志解析,供给增量数据订阅和消费

早期阿里巴巴由于杭州和美国双机房布置,存在跨机房同步的事务需求,完成方式主要是根据事务 trigger 获取增量改变。从 2010 年开端,事务逐渐测验数据库日志解析获取增量改变进行同步,由此衍生出了很多的数据库增量订阅和消费事务。

刚更新的数据居然查不到,MySQL你到底在做什么妖-上

canal官网图示.png

github 地址:github.com/alibaba/can…

1.2 SkyWalking 常识弥补:

SkyWalking 是一个可观测性渠道(Observability Analysis Platform 简称 OAP)和运用功能办理体系(Application Performance Management 简称 APM)。供给分布式链路追寻、服务网格(Service Mesh)遥测剖析、度量(Metric)聚合和可视化一体化解决计划。

下图即其链路追寻的展现作用,经过它能够直观看出一次恳求完好的履行轨迹,经过了哪些运用、访问了哪些中间件、恳求的关键信息是什么、各环节的履行耗时是多少、是否异常等。

刚更新的数据居然查不到,MySQL你到底在做什么妖-上

github 地址:skywalking.apache.org/

二、问询排查

2.1 整理数据流通

由于运用没有接入 SkyWalking,缺少直观完好 trace 信息的协助,你只能经过低效的、人工问询的方式整理有哪些运用、DB 什么类型、数据流通状况,经过一番交流后才了解到状况如下:

  1. 运用 A 将 MySQL 中 x 订单记载中 y 字段从 ccc 变成了 ddd
  2. canal 监听 DB 中订单表,从 binlog 中感知到 x 记载改变信息后,发到 MQ
  3. 运用 B 消费这个 MQ,收到这条音讯后,处理流程中会再恳求运用 A 的 Dubbo 接口,查询一些信息
  4. 运用 A 收到 Dubbo 恳求后,处理逻辑中还会从 MySQL 中查询这个 x 订单记载,但是!!!读出的状况字段竟然仍是 ccc
  5. DB 是读写别离,MySQL 主从同步采用的异步同步形式

2.2 确定可疑环节

根据前边掌握的状况,你在大脑中快速勾勒出如下这个数据流传图:

刚更新的数据居然查不到,MySQL你到底在做什么妖-上

经过这个数据流传图能够看出读数据有如下 3 种途径:

  • 6.1 读缓存
  • 6.2 读从库
  • 6.3 读主库

你反复思索之后推测 6.1 或 6.2 这两种途径很或许会读取到旧值,所以开端排查。

2.3 排查 Mybatis 缓存

你根据经历推测, 6.1 最有或许读不到新数据,缓存通常有进程内缓存、Redis 缓存,Mybatis 缓存这几种。进一步交流后,你确认了运用 A 并没有运用内存缓存和 Redis 缓存,搭档甚至有置疑数据库中间件中是否有缓存,这个置疑被你直接扫除了(数据库中间件中没有缓存),那就剩下 Mybatis 缓存这一处嫌疑了,所以你快速从大脑的常识库中翻出 Mybatis 两级缓存的机制原理。

2.3.1 扫除一级缓存的嫌疑

一级缓存默许是敞开的,是否一级缓存的问题呢?你持续剖析:

  • 按照现有 mapper 的用法,一个恳求中一切的 CRUD 操作都是在同一个 sqlSession 里面
  • 一个 sqlSession 内的一切查询操作都会保存到这个 sqlSession 内缓存中,即每个恳求都有一个专属于自己的一级缓存
  • 每个恳求的一级缓存阻隔,彼此互不搅扰
  • 运用 A 在 x 记载更新前,查询恳求中的一级缓存数据,不会被运用 A 在 x 记载更新后的查询恳求访问到。

刚更新的数据居然查不到,MySQL你到底在做什么妖-上

如此整理剖析后,你扫除了 Mybatis 一级缓存形成此问题的或许。

2.3.1 扫除二级缓存的嫌疑

然后你持续开端排查是否由二级缓存导致的,你的常识库显现:二级缓存在 sqlSession 之外,被 sqlSession 共享,即多个恳求能够共用同一个二级缓存,一、二级缓存的协作机制如下:

  • sqlSession 缓存的数据是先放在一级缓存中,当 sqlSession 会话提交或许关闭时会将一级缓存数据同步到二级缓存中
  • 用户查询时,会先去二级缓存中查找,若找不到才去一级缓存中查找

读二级缓存.png

这么看来如果时差符合,二级缓存的嫌疑很大,那是不是二级缓存的问题呢?此刻一个常识点在使劲的敲击你的大脑 【二级缓存需求手动敞开】 ,所以你抓紧咨询运用 A 是否敞开了二级缓存,但搭档一时间又搞不清楚这个开关的常识,所以你把敞开二级缓存的方式描述宣布:

  • 单个 mapper 敞开

    在需求敞开二级缓存的 XXXmapper.xml 文件中参与以下装备

<!--敞开单个mapper的二级缓存-->
<cache/>
  • 一切 mapper 都敞开

在 mybatis.xml 中参与以下装备

<settings>
<!--敞开一切mapper的二级缓存-->
<!--<settingname="cacheEnabled"value="true"/>-->
</settings>

运用 A 对照定论,没有敞开 Mybatis 的二级缓存。

如此整理剖析后,你又扫除了 Mybatis 二级缓存形成此问题的或许。

2.4 排查 binlog 同步

刚更新的数据居然查不到,MySQL你到底在做什么妖-上

根据上图你持续排查,此刻置疑到了 6.2 读从库这个环节,跟 DBA 核实得知,这个 MySQL 主从同步采用了异步同步计划;此刻你的常识库表示很为难:MySQL 异步同步机制并不熟悉,所以找到隔壁老王(canal、MQ 专家)请教,老王解释到:异步同步的机制中,master-DB 写 binlog 后履行提交,不等候 slave-DB 的同步状况;既然 canal 和 slave-DB 都是读取 binlog 数据之后再做处理,且无次序管控,那就有或许当运用 A 从 slave-DB 读 x 记载时,slave-DB 还未完成 x 记载的同步,状况如下图:

刚更新的数据居然查不到,MySQL你到底在做什么妖-上

同步延迟.png

一起老王还弥补,方才现已排查过 canal 和 MQ 的作业状况,DBA 也看过 DB 的监控信息,这几个体系的目标都很平稳没有颤动,如果有颤动的话,那出问题的应该也不只是这一条记载。

当掌握了这些信息后,你根本确定运用 A 是读了 slave-DB,由于你的数据库中间件,在读写别离的场景中,默许状况下读恳求是自动路由到 slave-DB 的,除非…,忽然你跟运用 A 核实,这个读恳求有没有指定强制读master-DB…,运用 A 的回复跟你的预期相差很大,这个恳求中他指定了读master-DB。

刚更新的数据居然查不到,MySQL你到底在做什么妖-上

为什么为什么读 master-DB,还能读到的是老数据,莫非是数据库中间件的路由机制有漏洞了?导演让你马上合作表演出了上图中的表情…OH MY GOD !!!

2.5 新的窘境

过了好一会儿,你镇定了下来,凭借你的刚强的魂灵,你确定不是数据库中间件的路由机制有漏洞,而此刻 DBA 也不认为 master-DB 有问题,运用 A 也不认为他指定读 master-DB 的代码有问题,老王也不认为他的 canal 读到的 binlog 有问题。

刚更新的数据居然查不到,MySQL你到底在做什么妖-上

面面相觑好久,大家心照不宣的望向了导演,而你作为主角,天然由你去问导演接下来要怎样演。

三、接入 SkyWalking

导演着急的大吼:“那谁,这都演完了,你剧本还没写出来嘛?”

只见编剧不慌不忙的走来后把剧本递给导演,导演照着剧本认真的读了起来:“缺失有效的可观测trace数据,又没有办法快速复现,或许只有天主知道是哪个环节有问题,要不问问天主?”

此刻忽然有人站起来说:”我演的是天主,运用 A、运用 B 接下来接一下 SkyWalking 吧,等下次复现时,大家就能根据链路信息来快速揭秘问题真相“。

所以你在群里宣布接入 SkyWalking 的文档,两个点很简单:

  1. 运用装备中心勾选接入 SkyWalking
  2. 日志装备文件中调整参与 traceId 占位符

整理剖析至此,世人没了方向,也都保留了各自的置疑,期待接入 SkyWalking 后再遇到,根据准确的信息来定位。

四、终章剧透

鄙人一章(终章)的剧本中,你是主角老王;上边这种为难的状况把你那股较真儿的劲头给激活了,之后你查阅了许多材料,进一步学习了 MySQL 的同步机制,在问题复现后,给出了 MySQL 同步机制有缺点的根因…。敬请期待终章,关键剧情如下:

  1. 运用 A、运用 B 之后接入了 SkyWalking
  2. 两周后,这个问题又呈现了
  3. SkyWalking 中 trace 信息表明运用 A 的确是读了 master-DB
  4. 老王经过进一步收集研讨发现,这是 MySQL 作业机制中天然存在的缺点
  5. 世人商定了后续的改进和规范调整,以应对这个缺点
终章传送门:《刚更新的数据竟然查不到,MySQL你到底在做什么妖-下》

五、最终说一句(请重视,莫错失)

如果这篇文章对您有协助,或许有所启示的话,欢迎三连重视大众号【 架构染色 】进行交流和学习。您的支持是我坚持写作最大的动力。

求一键三连:重视、点赞、转发。

本文正在参与「技能专题19期 闲谈数据库技能」活动