MYSQL 主从不一致的原因分析
数据库作为存储数据的组件,数据的一致性一定是要保证的前提,今天给出两个场景来分析数据不一致的原因。
binlog同步模式导致主从不一致#
在MYSQL 中主库向从库同步数据是利用binlog记录修改操作,然后将binlog传递给从库进行复制,binlog的格式有3种,
row
在对update,delete,insert语句进行记录时会进行修改的行数据进行记录。row
格式的坏处在于比较占用空间,比如更新十万行数据,那么row
格式将会把10万数据记录下来。
statement
只会将原始的sql语句记录下来。但是这种格式可能会引起主备不一致。
mixed
是前面两种格式的混合,MYSQL会自己去判断这条sql是不是会造成主备不一致,将引起主备不一致的sql记录成row
格式。
statement 为什么会主备不一致?#
举一个例子来说明下,statement主备不一致的原因,例如下面的sql
update navigation.t_account set id = uuid();
当你使用 类似uuid或者now这种动态函数时,那么在主库的生成结果将会和从库不同。造成数据的主备不一致。
为什么大多数时候我们还是用row#
大多时候,我们还是用row
格式写入binlog,这样带来的好处是便于恢复数据
,下面我举例说明下,
当你执行错delete语句
,能够通过binlog日志找到删除行的所有字段信息,不过需要注意的是,需要将binlog_row_image
参数设置为FULL
,才会记录所有字段信息,如果设置为MINIMAL
则只会记录删除字段信息。当你执行错update语句
,通过binlog记录的修改前后的整行数据,对数据进行恢复。当你执行错insert语句
,能够通过binlog找到插入数据的id,对错误插入的数据进行删除。
所以,为了避免主从不一致,还是选用row
格式记录binblog吧,或者至少还是选用mixed
主备切换导致主从不一致#
第二种主从不一致的场景是发生在主备切换时,我先直接说下结论,主备切换方式其实分可靠性优先方式与可用性优先方式。
可靠性优先方式,MYSQL服务可能会存在短暂的不可提供服务的时间段,可用性优先则是保证MYSQL在切换过程中都是可用的。
为了方便,下面我将主主数据库称为master,从数据库称为slave。
可靠性优先方式#
1,判断slave是否已经 seconds_behind_master
,是否小于5s或更短,seconds_behind_master
代表主从同步延迟的时间,如果小于5s,则继续下一步。
2,修改master的readonly
参数为true, 将master变为只读状态。
3,判断slave的主从同步延迟是否变为0,即seconds_behind_master 等于0,等于0后,继续下一步。
4,修改 slave的 readonly
参数改为false,将slave变为可读可写状态。
5,将业务请求转发到slave,原先master,修改为新master的从库。
这个切换过程,数据库是有一段时间不可写的,必须等待slave主从延迟同步变为0以后才行,所以这也是为什么要在seconds_behind_master
在一个较小的值才开始进行主备切换的原因。
可用性优先方式#
接着看下保证可用性优先的主备切换方式,在上述主备切换步骤中,我们去掉第三个步骤,也就是不等到主从同步完成就去切换主备。
现在假设现在的binlog为 row
格式。表定义为
mysql> CREATE TABLE `t` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `c` int(11) unsigned DEFAULT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB;
insert into t(c) values(1),(2),(3);
业务此时进行插入操作,
insert into t(c) values(4);
insert into t(c) values(5);
当在执行完第一个sql时,进行主备切换,且假设此时备库并没有完成第一条sql的同步。如下图所示,在插入4这条数据时,将slave改为可写,接着业务系统后续的写就往slave写入了5这条数据。注意此时master的4这条数据还没有同步到slave。
接着开始准备更改主备关系,如下图所示,更改关系前,有可能slave才会进行来自master的4这条数据的写入,但是因为slave中已经有id为4的数据了,所以会导致插入失败。
修改slave为master后,插入到之前从库的(4,5)这条数据 会同步到新的slave主机(即旧master),但是这个时候也会因为旧master有id为4的这条数据导致同步失败。主备同步就会自动停止。
可以看到,最后主从数据库中有id等于4这条数据不一样。
所以,可用性优先的主备切换方式是有可能导致主备不一致的。
数据库最重要还是数据的正确性
,拿许多业务场景来说,如果数据错乱了,是较难恢复的,但是如果业务失败了,还可以通过重试重新填充数据,怕就怕成功一半,失败一半。所以主备切换的时候尽量还是可靠性优先方式比较好。
最后,
自荐一波✅:
欢迎朋友们关注我的公众号📢📢:【蓝胖子的编程梦】!
学习容器知识🐳,性能监控🚀,Golang🐋 相关编程知识
作者:蓝胖子的编程梦
出处:https://www.cnblogs.com/hobbybear/p/18070737
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
2023-03-13 看了还不懂b+tree的本质就来打我