正常情况下,只要主库执行更新生成的所有binlog,都可以传到备库并被正确执行,备库就能达到跟主库一样的状态,这就是最终一致性。
这里我们再放上MySQL主备切换的流程图:

主备切换可能是一个主动的运维动作,如软件升级等。也可能是被动操作,如主库所在机器掉电等。
主备同步的过程通常有以下三步:
所谓主备延迟,就是同一个事务,在备库执行完成的时间和主库执行完成的事件之间的差值,也就是T3-T1。
我们可以在备库上执行show slave status命令,会返回seconds_bebind_master,用于表示当前备库延迟了多少秒。
实际上,在网络正常的时候,日志从主库传递给备库的时间是很短的。主要延迟的时间是在备库消费中转日志(relay log)速度,这个速度是要比主库生产binlog的速度要慢的。
第一种可能,有些部署条件下,备库所在机器的性能要比在主库所在的机器性能差。
因为习惯性认为备库的请求不好,没必要用那么好的机器。但是在发生主备切换的时候就比较麻烦。
第二种可能,备库的压力比较大。
因为大家比较重视主库,可能就会忽略备库的压力控制。备库上的查询可能耗费了大量的CPU资源,影响了同步速度,造成主备延迟。
解决办法可以采用一主多从的架构,让多个从库来分担压力。
第三种可能,大事务。
大事务很容易理解,因为主库上必须等待事务执行完成才会写入binlog,再传给备库。所以,如果一个事务在主库上面执行10分钟,那这个也会导致从库上延迟10分钟。
解决办法就是尽量避免一个事务执行过长的时间。
可靠性优先策略的主备切换流程主要有以下几步:
具体流程如下图所示(SBM代表seconds_bebind_master):

可以看到,这个切换流程中是有不可用时间的。因为在步骤2之后,主库A和备库B都处于readonly状态,也就是说系统处于不可写状态,直到步骤5才恢复。正是因为这个原因,所以在第一步菜肴确保主从延迟的时间尽可能短。
因为可靠性优先策略存在不可用时间,所以出现了可用性优先策略,这个方法几乎可以将不可用时间降为0。
可用性优先策略,就是把步骤4、5调整到最开始执行。也就是说不等主备数据同步,直接连接切到备库B,且让备库B可以读写。
但是这种可用性优先策略可能会存在主备不一致的情况,如下的例子,我们先建立下面这张表:
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);
假设,主库上其他的数据表有大量的更新,导致主备延迟5秒,在插入一条c=4的语句后,进行主备切换。
在使用可用性优先策略,且binlog_format=mixed是进行主备切换,过程如下图:

我们分析下上面的流程:
从上面的步骤执行完的结果来看,库A和库B出现了不一致。这是因为可用性优先策略流程导致的。这样就就会有两行数据不一致。
那如果设置binlog_format=row,会发生什么情况呢?如下图所示:

我们分析下上面的流程:
因为binlog_format=row会记录插入行的具体值,所以最后进行主备同步的时候,会报错duplicate key error。这样就就会有一行数据不一致。
综上,我们可以得到以下结论:
来源:自己整理的MySQL实战45讲笔记