如何避免MYSQL主从延迟带来的读写问题?

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

image.png

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

主从复制的原理

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

image.png

1,从数据库(slave)会启动两个线程io_thread 和sql_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,可以获取如下结果

Pasted image 20240308162704.png

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

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

Pasted image 20240308162840.png

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

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

判断GTID 是否同步

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

什么是GTID值?

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

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

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

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

Pasted image 20240308165622.png

  • 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集合。如下图所示,

Pasted image 20240308165933.png

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,可以获取如下结果

Pasted image 20240308162704.png

可以看到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。

Pasted image 20240308171227.png

3, 在上一步如果触发超时即返回1,则直接读取主库,如果是=0 ,则直接读取从库。这样便能最大程度从从库读取数据。

文章转载自:蓝胖子的编程梦

原文链接:https://www.cnblogs.com/hobbybear/p/18061516

体验地址:引迈 - JNPF快速开发平台_低代码开发平台_零代码开发平台_流程设计器_表单引擎_工作流引擎_软件架构

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/737445.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

QML | 在QML中导入JavaScript资源、导入JavaScript资源、包含一个JavaScript 资源

01 在QML中导入JavaScript资源 JavaScript资源可以被QML文档和其他JavaScript通过相对或者绝对路径进行导入。如果使用相对路径,位置解析需要相对于包含import语句的QML文档或JavaScript资源的位置。如果JavaScript需要从网络资源中进行获取,组件的status属性会被设置为Loadi…

PyCM:Python中的混淆矩阵库

PyCM:Python中的混淆矩阵库 在机器学习和数据科学领域,评估模型的性能是至关重要的。混淆矩阵是一种常用的评估工具,用于可视化和量化分类模型的预测结果。PyCM是一个开源的Python库,提供了丰富的功能来计算和分析混淆矩阵。本文将…

【C++】STL(二) string容器

一、string基本概念 1、本质 string是C风格的字符串,而string本质上是一个类 string和char * 区别: char * 是一个指针 string是一个类,类内部封装了char*,管理这个字符串,是一个char*型的容器。 2、特点 1、stri…

R语言绘制桑基图教程

原文链接:R语言绘制桑基图教程 写在前面 在昨天3月10日,我们在知乎、B站等分享了功能富集桑基气泡图的绘制教程。相关链接:NC|高颜值功能富集桑基气泡图,桑基气泡组合图。 确实,目前这个图在文章中出现的频率相对比较…

Wilson威尔逊平滑

1、威尔逊平滑引入的动机 在曝光很少的情况下,计算出的CTR并不真实可靠,而样本数越大,CTR的比例才越准确,更能反应真实情况。 为了衡量样本数对于CTR信区间的影响,我们引入"威尔逊(Wilson&#xff0…

地球系统模式(CESM)

目前通用地球系统模式(Community Earth System Model,CESM)在研究地球的过去、现在和未来的气候状况中具有越来越普遍的应用。CESM由美国NCAR于2010年07月推出以来,一直受到气候学界的密切关注。近年升级的CESM2.0在大气、陆地、海…

STM32CubeMX 配置 STM32F103 工程:通过DAC输出正弦波

说明:STM32CubeMX 配置 STM32F103 工程,通过DAC输出正弦波,参考代码可自动计算频率,自动计算正弦数据。 先参考这篇文章配置时钟、工程输出的设置: STM32CubeMX 配置 STM32F103 工程:通过DAC生成三角波、…

关于遗传力常见的误解

大家好,我是邓飞,今天看了一篇非常好的文章,介绍了遗传力相关概念和计算方法,里面提到了常见的误解,这里汇总一下。 文献链接:https://excellenceinbreeding.org/sites/default/files/manual/EiB-M2_Herit…

STM32CubeMX学习笔记20——SD卡FATFS文件系统

1. FATFS文件系统简介 文件系统是操作系统用于明确存储设备或分区上的文件的方法和数据结构(即在存储设备上组织文件的方法)。操作系统中负责管理和存储文件信息的软件机构称为文件管理系统,简称文件系统;不带文件系统的SD卡仅能…

seo js转码工具

js转码工具作用 用于把js加密 如果不想让别人看到自己的js 代码就可以使用这个方法 js工具网址 https://tool.chinaz.com/js.aspx 效果

【大厂AI课学习笔记NO.74】人工智能产业技术架构

包括基础层、技术层和应用层。 人工智能的产业技术架构是一个多层次、多维度的复杂系统,它涵盖了从基础硬件和软件设施到高级算法和应用技术的全过程。这个架构通常可以分为三个主要层次:基础层、技术层和应用层。下面我将详细论述这三个层次及其细分内…

基于Yolo5模型的动态口罩佩戴识别安卓Android程序设计

禁止完全抄袭,引用注明出处。 下载地址 前排提醒:文件还没过CSDN审核,GitHub也没上传完毕,目前只有模型的.pt文件可以下载。我会尽快更新。 所使用.ptl文件 基于Yolo5的动态口罩佩戴识别模型的pt文件资源-CSDN文库 项目完整文…

升级ChatGPT4.0失败的解决方案

ChatGPT 4.0科普 ChatGPT 4.0是一款具有多项出众功能的新一代AI语言模型。以下是关于ChatGPT 4.0的一些关键特点和科普内容: 多模态:ChatGPT 4.0具备处理不同类型输入和输出的能力。这意味着它不仅可以接收文字信息,还能处理图片、视频等多…

C++17中auto作为非类型模板参数

非类型模板参数是具有固定类型的模板参数,用作作为模板参数传入的constexpr值的占位符。非类型模板参数可以是以下类型: (1).整型; (2).枚举类型; (3).std::nullptr_t; (4).指向对象的指针或引…

vscode中解决驱动编写的时候static int __init chrdev_init()报错的问题

目录 错误出错原因解决方法 错误 在入口函数上,出现 expected a ; 这样的提示 出错原因 缺少了 __KERNEL __ 宏定义 解决方法 补上__KERNEL__宏定义 具体做法:在vscode中按下ctrlshiftp ,输入:C/C:Edit Configurations&#xff0…

手把手教使用静默 搭建Oracle 19c 一主一备ADG集群

一、环境搭建 主机IPora19192.168.134.239ora19std192.168.134.240 1.配置yum源 1.配置网络yum源 1.删除redhat7.0系统自带的yum软件包; rpm -qa|grep yum >oldyum.pkg 备份原信息rpm -qa|grep yum|xargs rpm -e --nodeps 不检查依赖,直接删除…

EE5437-IOT(Lecture 07-Control Interface System)

Review: introduce the micro input device system(MIDS) • The calibration and testing has been covered • The introduction to filters with the example called Butterworth filter and the maths have been also demonstrated. …

鸿蒙Harmony应用开发—ArkTS声明式开发(基础手势:CalendarPicker)

日历选择器组件,提供下拉日历弹窗,可以让用户选择日期。 说明: 该组件从API Version 10开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。 子组件 无 接口 CalendarPicker(options?: CalendarOptions) …

跨境账号养号怎么做?Facebook、亚马逊运营必看

之前我们讨论过很多关于代理器的问题。它们的工作原理是什么?在不同的软件中要使用那些代理服务器?这些代理服务器之间的区别是什么?什么是反检测浏览器等等。 除了这些问题,相信很多人也会关心在使用不同平台的时代理器的选择问题。比如,为什么最好…

Mybatis操作sql报错ibatis.binding.BindingException: Parameter ‘empId‘ not found.

你们好,我是金金金。 场景 在使用Mybatis操作sql语句过程当中,更新操作,报错信息如下:Caused by: org.apache.ibatis.binding.BindingException: Parameter ‘empId’ not found. Available parameters are [arg1, arg0, param1, …