MYSQL 主从不一致的原因分析
数据库作为存储数据的组件,数据的一致性一定是要保证的前提,今天给出两个场景来分析数据不一致的原因。
binlog 同步模式导致主从不一致
在 MYSQL 中主库向从库同步数据是利用 binlog 记录修改操作,然后将 binlog 传递给从库进行复制,binlog 的格式有 3 种,
row
在对 update,delete,insert 语句进行记录时会进行修改的行数据进行记录。row
格式的坏处在于比较占用空间,比如更新十万行数据,那么row
格式将会把 10 万数据记录下来。
statement
只会将原始的 sql 语句记录下来。但是这种格式可能会引起主备不一致。
mixed
是前面两种格式的混合,MYSQL 会自己去判断这条 sql 是不是会造成主备不一致,将引起主备不一致的 sql 记录成row
格式。
statement 为什么会主备不一致?
举一个例子来说明下,statement 主备不一致的原因,例如下面的 sql
当你使用 类似 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
格式。表定义为
业务此时进行插入操作,
当在执行完第一个 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 这条数据不一样。
所以,可用性优先的主备切换方式是有可能导致主备不一致的。
数据库最重要还是数据的正确性
,拿许多业务场景来说,如果数据错乱了,是较难恢复的,但是如果业务失败了,还可以通过重试重新填充数据,怕就怕成功一半,失败一半。所以主备切换的时候尽量还是可靠性优先方式比较好。
文章转载自:蓝胖子的编程梦
评论