写点什么

MYSQL 主从不一致的原因分析

  • 2024-03-14
    福建
  • 本文字数:1820 字

    阅读完需:约 6 分钟

数据库作为存储数据的组件,数据的一致性一定是要保证的前提,今天给出两个场景来分析数据不一致的原因。


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 这条数据不一样。


所以,可用性优先的主备切换方式是有可能导致主备不一致的。


数据库最重要还是数据的正确性,拿许多业务场景来说,如果数据错乱了,是较难恢复的,但是如果业务失败了,还可以通过重试重新填充数据,怕就怕成功一半,失败一半。所以主备切换的时候尽量还是可靠性优先方式比较好。


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

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

体验地址:http://www.jnpfsoft.com/?from=001

用户头像

还未添加个人签名 2023-06-19 加入

还未添加个人简介

评论

发布
暂无评论
MYSQL 主从不一致的原因分析_MySQL_不在线第一只蜗牛_InfoQ写作社区