您现在的位置是:亿华云 > 数据库

MySQL读写分离,写完读不到问题如何解决

亿华云2025-10-03 06:44:03【数据库】6人已围观

简介本文转载自微信公众号「程序员历小冰」,作者历小冰 。转载本文请联系程序员历小冰公众号。大家好,我是历小冰。今天我们来详细了解一下主从同步延迟时读写分离发生写后读不到的问题,依次讲解问题出现的原因,解决

本文转载自微信公众号「程序员历小冰」,写分作者历小冰 。离写转载本文请联系程序员历小冰公众号。完读问题

大家好,何解我是写分历小冰。

今天我们来详细了解一下主从同步延迟时读写分离发生写后读不到的离写问题,依次讲解问题出现的完读问题原因,解决策略以及 Sharding-jdbc、何解MyCat 和 MaxScale 等开源数据库中间件具体的写分实现方案。

写后读不到问题

MySQL 经典的离写一主两从三节点架构是大多数创业公司初期使用的主流数据存储方案之一,主节点处理写操作,完读问题两个从节点处理读操作,何解分摊了主库的写分压力。

但是离写,有时候可能会遇到执行完写操作后,完读问题立刻去读发现读不到或者读到旧状态的尴尬场景。这是由于主从同步可能存在延迟,在主节点执行完写操作,再去从节点执行读操作,读取了之前旧的状态。

上图展示了此类问题出现的操作顺序示意图:

•客户端首先通过代理向主节点 Master 进行了写入操作

•紧接着第二步去从节点 Slave A 执行读操作,服务器托管此时 Master 和 Slave A 之间的同步还未完成,所以第二步的读操作读取到了旧状态

•当第五步再次进行读操作时,此时同步已经完成,所以可以从 Slave B 中读取到正确的状态。

下面,我们就来看一下为什么会出现此类问题。

MySQL 主从同步

理解问题背后发生的原因,才能更好的解决问题。MySQL 主从复制的过程大致如下图所示,本篇文章只讲解同步过程中的流程,建立同步连接和失联重传不是重点,暂不讲解,感兴趣的同学可以自行了解。

MySQL 主从复制,涉及主从两个节点,一共四个四个线程参与其中:

主节点的 Client Thread,处理客户端请求的线程,执行如图所示的1~5步骤,2,3,4步骤是网站模板为了保证数据的一致性和尽量减少丢失,第三步骤时会通知 Dump Thread; 主节点的 Dump Thread,接收到 Client Thread 通知后,负责读取本地的 binlog 的数据,将 binlog 数据,binlog 文件名 以及当前发送 binlog 的位置信息发送给从节点; 从节点的 IO Thread 负责接收 Dump Thread 发送的 binlog 数据和相关位置信息,将其追加到本地的 relay log 等文件中; 从节点的 SQL Thread 检测到 relay log 追加了新数据,则解析其内容(其实就是解析 binlog 文件的内容)为可以执行的 SQL 语句,然后在本地数据执行,并记录下当前执行的 relay log 位置。

上述是默认的异步同步模式,我们发现,从主节点提交成功到从节点同步完成,中间间隔了6,7,8,9,10多个步骤,源码下载涉及到一次网络传输,多次文件读取和写入的磁盘 IO 操作,以及最后的 SQL 执行的 CPU 操作。

所以,当主从节点间网络传输出现问题,或者从节点性能较低时,主从节点间的同步就会出现延迟,导致文章一开始提及的写后读不到的问题。在高并发场景,从节点一般要过几十毫秒,甚至几百毫秒才能读到最新的状态。

常见的解决策略

一般来讲,大致有如下方案解决写后读不出问题:

•强制走主库

•判断主备无延迟

•等主库位点或 GTID 方案

强制走主库

强制走主库方案最容易理解和实现,它也是最常用的方案。顾名思义,它就是强制让部分必须要读到最新状态的读操作去主节点执行,这样就不会出现写后读不出问题。这种方案问题在于将一部分读压力给了主节点,部分破化了读写分离的目的,降低了整个系统的扩展性。

一般主流的数据库中间件都提供了强制走主库的机制,比如,在 sharding-jdbc 中,可以使用 Hint 来强制路由主库。

它的原理就是在 SQL 语句前添加 Hint,然后数据库中间件会识别出 Hint,将其路由到主节点。

下面,我们就来看一下如果要去从库查询,并且要避免过期读的方案,并分析各个方案的优缺点。

判断主备无延迟

第二种方案是使用 show slave status 语句结果中的部分值来判断主从同步的延迟时间:

> show slave status 

很赞哦!(38)