在MYSQL 部署架构选型上,许多公司都会用到主从读写分离的架构,如下是一个一主一从的架构,主库master负责写入,从库slave进行读取。

但是既然是读写分离,必然会面临这样一个问题,当在主库上进行更新后,有可能数据还没来得及同步到从库,但是这个时候又有读数据的需求,为了能正确读取出数据,这个时候就只有读主库了。但是这样做增加了主库的压力,违反了我们做读写分离的初衷。所以这一节我们就来针对这种情况探讨下,如何尽量的避免对主库的压力,尽量的从从库读取数据。

主从复制的原理

在探讨解决方案前,我们先要对主从复制的原理有所了解,数据库的操作都会记录到binlog,如下图所示,

1,从数据库(slave)会启动两个线程io_threadsql_thread ,通过io_thread将自身与主数据库(master)建立连接。

2,slave向master发出要同步的位置信息(包含同步的文件名和偏移量),表示需要从该位置发起同步。

3,主数据库master 将位置点后的binlog发送给slave, slave获取到本地形成relay log(中转日志)。

4, 接着通过sql_thread解析relay log,执行sql。

从主从复制的过程可以看出,主从延迟时间是 在主库master执行sql的时间点到从库通过解析relay log 执行sql后的时间点之间的差值。如果应用程序能够在master写入数据后等待这么一段时间,再去slave读取,就能正确的读取出来数据了。

但是这个时间差值是不确定的,究竟应用程序需要等待多久才去读取slave,就成了我们需要思考的问题。

如何避免延迟期间的主从数据不一致

比起在写入数据后读取主库或者写入数据后sleep一段时间读取从库,我给出两个我觉得比较靠谱点的方法。

判断位点是否同步

第一种方法是通过等待slave 将master写入数据后的 binlog的位点同步完成再对slave进行读取。

每次修改型sql的执行会将master的binlog 的位点(日志偏移量)前移,如果在修改型sql执行完成后,能够获取到master的binlog 位点,并且在客户端阻塞等待slave同步该位点完毕,再从slave读取就可以了。

MYSQL中提供了一个函数select master_pos_wait(file, pos[, timeout]) 用于在slave上执行等待master节点上的位点同步完成,其中file,和pos是在master上的文件和位点,timeout 为了让master_pos_wait 函数在timeout秒内没有返回,则会直接触发超时返回。

返回结果解析,

  • 返回结果正常情况下是一个大于0的整数,表示从pos位点开始完成了多少个事务。
  • 如果直接返回结果0,则说明在执行select master_pos_wait(file, pos[, timeout]) 时,位点已经同步完成。
  • 如果触发超时则返回-1。
  • 如果执行期间slave发生错误,则返回NULL。

所以,在判断是否应该在写入数据后读从库的逻辑,我们可以这样来写,

1, 在master写入数据后立马执行 show master status,可以获取如下结果

可以看到master的binlog文件名称以及位点。

2, 在slave上执行 select master_pos_wait('mysql-bin.232011',3129472,1);,如果1s内没有返回,则直接返回-1。

3, 在上一步如果触发超时返回返回-1,则直接读取主库,如果是>=0 的值,则直接读取从库。

这样便能最大程度从从库读取数据。

判断GTID 是否同步

接着,我们来看下第二种方式,其实第二种方式和通过位点的方式类似,不同的是slave判断是否将数据同步完成的依据是看GTID的值。

什么是GTID值?

GTID 的全称是 Global Transaction Identifier,全局事务 ID,是一个事务在提交的时候生成的,是这个事务的唯一标识。

MYSQL开启 GTID 模式的方式是 在启动一个 MySQL 实例的时候,加上参数 gtid_mode=onenforce_gtid_consistency=on

每个事务是和GTID 值一一对应的,每个MYSQL实例会维护一个GTID 集合,来表示实例执行过的事务。

在slave节点上,通过show slave status 可以看到 GTID集合,如下图所示,

  • Auto_Position=1 ,表示这对主备关系使用了 GTID 协议。
  • Retrieved_Gtid_Set,是备库收到的所有日志的 GTID 集合。
  • Executed_Gtid_Set,是备库所有已经执行完成的 GTID 集合。

如果Executed_Gtid_Set 等于Retrieved_Gtid_Set 说明slave将从master那里获取到的binlog全部执行完毕。

在master节点执行 show master status,也能看到GTID集合,Executed_Gtid_Set 为master节点执行过的GTID集合。如下图所示,

GTID 模式下判断同步的步骤

在GTID 模式下,从库slave从主库master取binlog的逻辑将不再是直接告诉master 要取的文件和位点了,而是由slave将自身的GTID集合告诉master。

master再结合自身的GTID集合,找出在master中有但是在slave中没有的GTID集合,然后从binlog中找到第一个不在GTID集合中的事务,从该事务的binlog位点开始,往后读取binlog发送给slave。

MYSQL针对于GTID同样提供 了一个函数select wait_for_executed_gtid_set(gtid_set, 1); 来让slave去判断对master执行过的gtid_set 是否已经同步完成。

wait_for_executed_gtid_set 函数的返回结果解析如下,

  • 如果slave 执行的事务中包含传入的 gtid_set,返回 0。
  • 如果等待1s后还没同步完成,则返回1。

所以在GTID 模式下的,在判断是否应该在写入数据后读从库的逻辑,我们可以这样来写,

1, 在master写入数据后立马执行 show master status,可以获取如下结果



可以看到master的Executed_Gtid_Set的值。

2, 在slave上执行

select wait_for_executed_gtid_set('76cd5ea1-c541-11ee-87ef-fa163eefe144:1-56382789,
808d2fb8-687b-11ec-b8b9-fa163e410530:1-144078103,
9081c19b-63de-11ed-9755-fa163eb8b97f:1-1093294115', 1);

,如果1s内没有返回,则直接返回1。

3, 在上一步如果触发超时即返回1,则直接读取主库,如果是=0 ,则直接读取从库。

这样便能最大程度从从库读取数据。

自荐一波:

欢迎朋友们关注我的公众号:【蓝胖子的编程梦】!

欢迎点赞 、收藏 、关注 三连支持一下~

我是蓝胖子,下期见~

如何避免MYSQL主从延迟带来的读写问题?的更多相关文章

  1. 架构师必备:MySQL主从延迟解决办法

    上一篇文章介绍了MySQL主从同步的原理和应用,本文总结了MySQL主从延迟的原因和解决办法.如果主从延迟过大,会影响到业务,应当采用合适的解决方案. MySQL主从延迟的表现 先insert或upd ...

  2. MySQL主从延迟如何解决?

    我们知道生产环境中经常会遇到MySQL主从延迟问题,从原理上也能看出主库的事务提交是并发模式,而从库只有一个SQL线程负责解析,所以本身上就可能存在延迟. 延迟的主要原因在于: 1.从库的配置往往没有 ...

  3. Mysql主从配置,实现读写分离

    大型网站为了软解大量的并发访问,除了在网站实现分布式负载均衡,远远不够.到了数据业务层.数据访问层,如果还是传统的数据结构,或者只是单单靠一台服务器扛,如此多的数据库连接操作,数据库必然会崩溃,数据丢 ...

  4. 黄聪:Mysql主从配置,实现读写分离

    大型网站为了软解大量的并发访问,除了在网站实现分布式负载均衡,远远不够.到了数据业务层.数据访问层,如果还是传统的数据结构,或者只是单单靠一台服务器扛,如此多的数据库连接操作,数据库必然会崩溃,数据丢 ...

  5. mysql主从延迟高的原因

    1.1.1故障1:从库数据与主库冲突 1 2 3 4 5 6 show slave status; 报错:且show slave status\G Slave_I/O_Running:Yes Slav ...

  6. 一次线上MySQL主从延迟排查

    今天早上来上班,发现zabbix一直告警主从延迟,mysql slave Seconds_Behind_Master (mysql.slave_status[Seconds_Behind_Master ...

  7. 面试官:咱们来聊一聊mysql主从延迟

    背景 前段时间遇到一个线上问题,后来排查好久发现是因为主从同步延迟导致的,所以今天写一篇文章总结一下这个问题希望对你有用.如果觉得还不错,记得加个关注点个赞哦 思维导图 思维导图 常见的主从架构 随着 ...

  8. 基于mysql主从同步的proxy读写分离

    mysql-proxy 简介 MySQL Proxy是一个处于你的client端和MySQL server端之间的简单程序,它可以监测.分析或改变它们的通信.它使用灵活,没有限制,常见的用途包括:负载 ...

  9. MySQL 主从延迟几万秒 Queueing master event to the relay log(转)

    数据库版本Server version:    5.6.24-log Source distribution 问题描述 数据采集平台业务数据库由于批量灌数据导致主从延迟上万秒. 复制线程长期处于Que ...

  10. MySQL 主从延迟的常见原因及解决方法

    承蒙大家的支持,刚上市的<MySQL实战>已经跃居京东自营数据库图书热卖榜第 1 名,收到的反馈也普遍不错.对该书感兴趣的童鞋可通过右边的链接购买.目前,京东自营有活动,只需 5 折. 主 ...

随机推荐

  1. 修改微信PC通知声音

    安装软件 下载地址如下 点我下载 提取码:1314 找到微信的位置 选择版本号文件夹进去 搜索关键词:WeChatResource.dll 拖拽到软件当中,选择如下分类 118是通知声音 119是来电 ...

  2. 基于NET Core 的Nuget包制作、发布和运用流程

    开发缘由:公司需要调用天眼查-开放平台 ,验证客户的的营业执照信息是否在存续期,并将企业基本信息返回,之后和使用百度图文识别的企业信息进行对照是否一致. 前期准备 在网站中注册后,需要够买套餐.之后点 ...

  3. Unity字体和画面花屏处理

    字体花屏和相机渲染花屏,这两者的表现有明显的差异. 字体花屏 字体花屏是持续性的,直到组件被刷新,或字体图集被刷新.目前在我们项目中当游戏启动时,就会填充游戏用到的所有字符到贴图中,所以并没有遇到此问 ...

  4. 基于50W携程出行攻略构建事件图谱(含码源):交通工具子图谱、订酒店吃饭事件图谱等

    基于50W携程出行攻略构建事件图谱(含码源):交通工具子图谱.订酒店吃饭事件图谱等 项目构成 本项目由两个部分的组成,具体包括语料的获取以及基于语料的事件挖掘两个部分,具体项目目录包括: news_s ...

  5. 错误解决:ElasticSearch SearchResponse的Hits[]总是比totalHits少一条记录

    在做ElasticSearch查询操作的时候,发现Hits[].length总是比totalHits.value少1.代码如下: SearchRequest request = new SearchR ...

  6. CTAS建表时报错ORA-65114

    环境: Oracle 19.16 多租户架构 1.问题现象: SQL> create table T1 as select * from v$active_session_history * E ...

  7. ASP.NET Core分布式项目实战(oauth密码模式identity server4实现)--学习笔记

    任务12:oauth密码模式identity server4实现 密码模式比客户端模式更加严格,需要第三方输入用户名和密码之后才可以访问 API 在 IdentityServerCenter 的 Co ...

  8. Unicode编码的魅力:跨语言交流的桥梁

    引言: Unicode编码是一种用于表示世界上所有字符的标准编码方式.它解决了字符集兼容性和多语言文本处理的难题,成为实现全球化软件的关键技术.本文将深入探讨Unicode编码的优点与缺点,并介绍它在 ...

  9. Codeforces Round #821 (Div. 2) A-E

    比赛链接 A 题解 知识点:贪心. 下标模 \(k\) 相同分为一组,共有 \(k\) 组,组间不能互换,组内任意互换. 题目要求连续 \(k\) 个数字,一定能包括所有的 \(k\) 组,现在只要在 ...

  10. python 学习随笔1121

    Python 数据处理几个好用又简单的库: json re string pandas 与系统交互: subprocess os