《MySQL实战45讲》——学习笔记24 “Master/Slave主备同步机制“

news2024/12/28 17:50:03

binlog可以用来归档,也可以用来做主备同步,binlog在MySQL的各种高可用方案上扮演了重要角色;

本篇主要介绍MySQL主备(M-S结构)的基本原理、不同格式binlog的优缺点和设计者的思考、MySQL双主结构和循环复制问题(双M结构)相关知识,这些点可以说是所有MySQL高可用方案的基础,在这之上演化出了诸如多节点、半同步、MySQL group replication等相对复杂的方案;在做系统开发时候,也能借鉴这些设计思想;

MySQL主备的基本原理

以上是主从结构以及主从切换的示例,客户端的读写都直接访问主库节点,而备库只是将主库的更新都同步过来,到本地执行;

此过程中,备库被设置成只读(readonly)模式,这样做有以下几个考虑:

  • 备库是不允许业务写入的,将备库设置为只读可以防止误写操作;

  • 可以用readonly状态,来判断节点的角色;

  • 即使备库设置成readonly状态,readonly设置对超级(super)权限用户是无效的,而用于同步更新的线程就具备超级权限,不影响备库做同步更新;

主从节点同步的细节

可以看到:

  1. 主库接收到客户端的更新请求后,执行内部事务的更新逻辑,同时写binlog;

  1. 备库B跟主库A之间维持了一个长连接;

  1. 主库A内部有一个线程,专门用于服务备库B的这个长连接;

一个事务日志同步(长连接)的完整过程

  • 设置主库属性:在备库B上通过change master命令,设置主库A的IP、端口、用户名、密码,以及要从哪个位置开始请求binlog,这个位置包含文件名和日志偏移量;

  • 启动备库:在备库B上执行start slave命令,这时候备库会启动两个线程,就是图中的io_thread和sql_thread;其中io_thread负责与主库建立连接;

  • 主库传输日志:主库A校验完用户名、密码后,开始按照备库B传过来的位置,从本地读取binlog,发给B;

  • 备库更新同步:备库B拿到binlog后,写到本地文件,称为中转日志(relaylog);sql_thread读取中转日志,解析出日志里的命令,并执行;

binlog的三种格式对比:statement / row / mixed

例子

为了便于描述binlog的这三种格式间的区别,用一个例子说明,下面建了一个表,并初始化几行数据;

mysql> CREATE TABLE `t` (
  `id` int(11) NOT NULL,
  `a` int(11) DEFAULT NULL,
  `t_modified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  KEY `a` (`a`),
  KEY `t_modified`(`t_modified`)
) ENGINE=InnoDB;

insert into t values(1,1,'2018-11-13');
insert into t values(2,2,'2018-11-12');
insert into t values(3,3,'2018-11-11');
insert into t values(4,4,'2018-11-10');
insert into t values(5,5,'2018-11-09');

执行删除语句:

mysql> delete from t /*comment*/  where a>=4 and t_modified<='2018-11-10' limit 1;
  • 当 binlog_format=statement 时,binlog 里面记录的就是 SQL 语句的原文,包括注释

用show binlog events命令看binlog中的内容;

分析:第一行先忽略,跟主备切换有关;第二行是一个BEGIN,跟第四行的COMMIT(XID=61)对应,表示中间是一个事务;第三行就是真实执行的语句了;可以看到,binlog“忠实”地记录了SQL命令,甚至连注释也一并记录了

  • statement格式,并且语句中有limit,这个命令可能是unsafe的

为了说明statement和row格式的区别,这里执行showwarnings命令发现运行这条delete命令产生了一个warning;

分析:这是因为delete带limit,很可能会出现主备数据不一致的情况;

比如上面这个例子:如果delete语句使用的是索引a,那么会根据索引a找到第一个满足条件的行,也就是说删除的是a=4这一行;但如果使用的是索引t_modified,那么删除的就是t_modified='2018-11-09’也就是a=5这一行;

由于statement格式下,记录到binlog里的是语句原文,因此可能会出现这样一种情况:在主库执行这条SQL语句的时候,用的是索引a;而在备库执行这条SQL语句的时候,却使用了索引t_modified;走不同的索引limit 1时找到的记录不一致,因此,MySQL认为这样写是有风险unsafe的;

  • row格式,则不会出现语句中有limit可能引起的unsafe问题

把binlog的格式改为binlog_format='row',看看这时候binog中的内容;

可以看到,与statement格式的binlog相比,前后的BEGIN和COMMIT是一样的;但是,row格式的binlog里没有了SQL语句的原文,而是替换成了两个event:Table_map和Delete_rows;

仅通过上图是看不到详细信息的,还需要借助 mysqlbinlog 工具,用下面这个命令解析和查看 binlog 中的内容;

可见,使用row格式的时候,binlog里面记录了真实删除行的主键id,这样binlog传到备库去的时候,就肯定会删除id=4的行,不会有主备删除不同行的问题

为什么会有 mixed 格式的 binlog?

基于上面的信息,来讨论一个问题:为什么会有mixed这种binlog格式的存在场景?

解释:

  • 因为statement格式可能会导致主备不一致,所以要使用row格式;

  • row格式的缺点是,很占空间;比如你用一个delete语句删掉10万行数据,用statement的话就是一个SQL语句被记录到binlog中,占用几十个字节的空间;但如果用row格式的binlog,就要把这10万条记录都写到binlog中;

  • 不仅占用更大的空间,同时写row格式的binlog也要耗费IO资源

所以,MySQL就取了个折中方案,也就是有了mixed格式的binlog;

mixed格式的意思是,MySQL自己会判断这条SQL语句是否可能引起主备不一致,如果有可能,就用row格式,否则就用statement格式;也就是说,mixed格式可以利用statment格式的优点,同时又避免了数据不一致的风险;

建议使用row格式

尽管上面解释了mixed格式存在的原因,现在越来越多的场景要求把MySQL的binlog格式设置成row;这么做的理由有很多,其中重要的一个好处就是:恢复数据

通过上面的分析可知,row格式的binlog会把被修改的行的整行信息保存起来;下面从delete、insert和update这3种SQL语句的角度,来分析row格式下数据恢复的思路:

  • 恢复delete:如果在执行完一条delete语句以后,发现删错数据了,可以直接把binlog中记录的delete语句转成insert,把被错删的数据插入回去就可以恢复了;

  • 恢复insert:row格式下,insert语句的binlog里会记录所有的字段信息,这些信息可以用来精确定位刚刚被插入的那一行;这时把insert语句转成delete语句,删除掉这被误插入的一行数据就可以了;

  • 恢复update:如果执行的是update语句的话,binlog里面会记录修改前整行的数据和修改后的整行数据;如果你误执行了update语句的话,只需要把这个event前后的两行信息对调一下,再去数据库里面执行,就能恢复这个更新操作了;

双M结构下的循环复制问题

上面介绍的是M-S结构,但实际生产上使用比较多的是双M结构,它的一个好处就是切换M的时候就不用再修改主备关系

要注意,一般说双M是仅仅是将AB之间设置为互为主备,任何时刻只会有一个节点在接受client的更新请求

双M结构还有一个问题需要解决——循环复制问题

循环复制问题:业务逻辑在节点A上更新了一条语句,然后再把生成的binlog发给节点B,节点B执行完这条更新语句后也会生成binlog;双M结构下,节点A同时是节点B的备库,相当于又会把节点B新生成的binlog拿过来执行了一次,然后节点A和B间,会不断地循环执行这个更新语句,也就是循环复制了;

如何解决?

实际上,MySQL在binlog中记录了这个命令第一次执行时所在实例的serverid;用下面的逻辑来解决两个节点间的循环复制的问题:

  • 规定两个库的serverid必须不同,如果相同,则它们之间不能设定为主备关系;

  • 一个备库接到binlog并在重放的过程中,生成与原binlog的serverid相同的新的binlog;

  • 每个库在收到从自己的主库发过来的日志后,先判断serverid,如果跟自己的相同,表示这个日志是自己生成的,就直接丢弃这个日志;

按照这个逻辑,如果设置了双M结构,日志的执行流就会变成这样:

  • 从节点A更新的事务,binlog里面记的serverid=A;

  • 传到节点B执行一次以后,节点B生成的binlog的serverid也是A;

  • 再传回给节点A,A判断到这个serverid=A与自己的相同,就不会再处理这个日志;所以,死循环在这里就断掉了;

但是,循环复制偶尔还是会发生的

case1:一种场景是,在一个主库更新事务后,用命令set global server_id=x修改了server_id;等日志再传回来的时候,发现server_id跟自己的server_id不同,就只能执行了;

case2:做数据库迁移时,节点复制的场景可能出现循环复制;如下:

解决让某个节点临时忽略某个server_id;然后再恢复

例如A和A'上出现了循环复制,可以在A或者A’上,执行如下命令:

stop slave;
CHANGE MASTER TO IGNORE_SERVER_IDS=(server_id_of_B);
start slave;

这样这个节点收到日志后就不会再执行;过一段时间后,再执行下面的命令把这个值改回来:

stop slave;
CHANGE MASTER TO IGNORE_SERVER_IDS=();
start slave;

下篇文章:待定

本章参考:24 | MySQL是怎么保证主备一致的?

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

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

相关文章

关于 Linux 系统

个人主页:ζ小菜鸡 大家好我是ζ小菜鸡&#xff0c;小伙伴们&#xff0c;让我们一起来学习Linux系统。 如果文章对你有帮助、欢迎关注、点赞、收藏(一键三连) 目录 一、Linux系统的组成 二、Linux 命令行的操作 三、Linux 目录结构 四、文件基本操作 五、用户及文件权限管…

jspssm小型药店药品管理系统

目 录 第一章 概述 1 1.1 研究背景 1 1.2开发意义 1 1.3 研究现状 1 1.4 研究内容 2 1.5论文结构 2 第二章 开发技术介绍 3 2.1 系统开发平台 3 2.2 平台开发相关技术 3 2.2.1 JSP技术介绍 3 2.2.2 Mysql数据库介绍 3 2.2.3 B/S架构 …

excel排名技巧:万能透视表加筛选找出销售冠军

在一组数据中统计单项排名第一的人员名单&#xff0c;如果用函数&#xff0c;我们需要考虑不同项目业绩相等的查找问题&#xff0c;需要考虑同项目业绩相等的查找问题。但如果用数据透视表加筛选&#xff0c;一切就很简单了。最后要么逐条地复制粘贴&#xff0c;要么用技巧合并…

ChatGPT 逆天测试,结局出乎预料

目录一、数学解题能力二、编程能力三、日常生活咨询四、问一些离谱的问题&#xff0c;它有啥反应&#xff1f;五、逆天大测试一、数学解题能力 据说 ChatGPT 会做数学题&#xff0c;给他几个条件不充分的问题&#xff0c;看看他是否真的会思考。 这家伙心理素质真好&#xff…

Uniswap 解析:恒定乘积做市商模型Constant Product Market Maker Model 的Vyper 实作

大纲 一. 前言 二. 恒定乘积做市商模型Constant Product Market Maker Model 1. 计入手续费 2. 程式码结构 3. 演算法核心与实作 4. 段落小结 三. 流动性Liquidity 1. 第一笔流动性注入、决定k值 2. 除了第一笔以外的情况 四. 结语 一. 前言 暨上一篇开始接触了Vyper 后&…

《吐血整理》保姆级系列教程-玩转Fiddler抓包教程(2)-初识Fiddler让你理性认识一下

1.前言 今天的理性认识主要就是讲解和分享Fiddler的一些理论基础知识。其实这部分也没有什么&#xff0c;主要是给小伙伴或者童鞋们讲一些实际工作中的场景&#xff0c;然后隆重推出我们的猪脚&#xff08;主角&#xff09;-Fiddler。 1.1工作场景 做app测试&#xff0c;你是…

SpringMVC的工作原理

SpringMVC的工作原理图&#xff1a; SpringMVC流程 1、 用户发送请求至前端控制器DispatcherServlet。 2、 DispatcherServlet收到请求调用HandlerMapping处理器映射器。 3、 处理器映射器找到具体的处理器(可以根据xml配置、注解进行查找)&#xff0c;生成处理器对象及处…

二叉树29:二叉搜索树中的插入操作

主要是我自己刷题的一些记录过程。如果有错可以指出哦&#xff0c;大家一起进步。 转载代码随想录 原文链接&#xff1a; 代码随想录 leetcode链接&#xff1a;701.二叉搜索树中的插入操作 题目&#xff1a; 给定二叉搜索树&#xff08;BST&#xff09;的根节点 root 和要插入…

苏嵌实训——day19

文章目录一、数据库1.1 在ubuntu中安装数据库1.2 数据库的操作1.2.1 数据库命令的分类1.2.2 常用的系统命令1.2.3 数据中的常用的语句1.3 sqlite数据库中常用api1. sqlite3_open2. int sqlite3_close(sqlite3 * db)3. sqlite3_exec4 sqlite3_get_table5 void sqlite3_free_tabl…

JavaEE12-Spring MVC程序开发

目录 1.什么是Spring MVC? 1.1.MVC定义 1.1.1.Model&#xff08;模型&#xff09; 1.1.2.View&#xff08;视图&#xff09; 1.1.3.Controller&#xff08;控制器&#xff09; 1.2.MVC和Spring MVC的关系 2.为什么要学Spring MVC? 3.怎么学Spring MVC? 3.1.Spring …

LeetCode——2319. 判断矩阵是否是一个 X 矩阵

一、题目 如果一个正方形矩阵满足下述 全部 条件&#xff0c;则称之为一个 X 矩阵 &#xff1a; 矩阵对角线上的所有元素都 不是 0 矩阵中所有其他元素都是 0 给你一个大小为 n x n 的二维整数数组 grid &#xff0c;表示一个正方形矩阵。如果 grid 是一个 X 矩阵 &#xff0c…

Linux的shell入门和版本控制(五)

0、前言 这部分简单介绍了Linux系统中的shell编程 1、服务监听 在Linux中的服务监听&#xff0c;相当于在windows中的任务管理器。常用指令&#xff1a; 示例一&#xff1a;查询进程 ps -aux|grep 要查询的程序名&#xff1a;这样查询会连带这条查询指令的进程一起查询出来。…

【深度学习笔记】LSTM的介绍及理解

问题 LSTM是深度学习语音领域必须掌握的一个概念,久仰大名,现在终于要来学习它了,真是世事无常,之前以为永远不会接触到呢,因此每次碰到这个就跳过了。 前言 LSTM (Long short-term memory,长短期记忆) 是一种特殊的RNN,主要是为了解决长序列训练过程中梯度消失与梯度…

Linux中SELinux、Shell简介、touch命令的应用知识总结

✅作者简介&#xff1a;热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏&#xff1a;Java案例分…

Spark SQL的生命旅程之底层解析

一、内容提要一条SQL语句是如何被解析的&#xff1f;一条SQL是如何转换为代码被机器执行的&#xff1f;SQL从逻辑计划到物理计划的转换经历了怎样的优化&#xff1f;二、Antlr4Antlr4 Java编写的强大的语法解析生成器# 命令行使用方式 curl -O https://raw.githubusercontent.c…

【MyBatis持久层框架】核心配置文件详细解读

文章目录1. 前言2. 多环境配置3. 类型别名4. 对象工厂5. 总结1. 前言 前面我们在使用 MyBatis 开发时&#xff0c;编写核心配置文件替换 JDBC 中的连接信息&#xff0c;解决了 JDBC 硬编码的问题。其实&#xff0c;MyBatis 核心配置文件中还可以配置很多的内容。 MyBatis 的配…

微信小程序java+nodejs+vue校园美食点餐评论餐饮配送系统

开发语言&#xff1a;Java 小程序前端框架&#xff1a;uniapp 小程序运行软件&#xff1a;微信开发者 后端技术:Ssm(SpringSpringMVCMyBatis)vue.js 后端开发环境:idea/eclipse 数据库:mysql 基于校园餐饮配送小程序的设计基于现有的手机&#xff0c;可以实现首页、个人中心、学…

[JavaWeb]JS

目录1.JavaScript特点2. script 标签写JS代码2.1 script 标签中写JS代码2.2 使用 script 标签引入 JS 文件2.3 使用 js 的两种方式,是二选一,不能混用3. 查看 JS 错误信息3.1 chrome 浏览器查看错误信息3.2 Microsoft Edge浏览器查看错误信息4.JS变量4.1 var定义变量4.2 JavaSc…

Go 基础Interface

Go Interface 今天学习下Golang语言中Interface基本语法与使用&#xff0c;通过代码示例了解Go编程中的接口及其实现。跟Java语言类似&#xff0c;在Go编程中&#xff0c;开发者可以使用接口来存储一组没有实现的方法。也就是说&#xff0c;接口的方法不会有方法体。 接口定义…

谷歌正开发苹果AirTag的竞品,但苹果Find My需求强劲

据安卓爆料专家 Mishaal Rahman 的消息&#xff0c;谷歌似乎正在开发苹果 AirTag 的竞品。 从图中可以看到&#xff0c;谷歌 Fast Pair 蓝牙快速配对中&#xff0c;出现了一个名为“Locator tag&#xff08;定位器标签&#xff09;”的分类&#xff0c;这一类别此前没有出现过…