主备延迟
与数据同步有关的时间点主要包括以下三个:
1. 主库A执行完成一个事务,写入binlog,我们把这个时刻记为T1;
2. 之后传给备库B,我们把备库B接收完这个binlog的时刻记为T2;
3. 备库B执行完成这个事务,我们把这个时刻记为T3。
所谓主备延迟,就是同一个事务,在备库执行完成的时间和主库执行完成的时间之间的差值,也就是T3-T1。
你可以在备库上执行show slave status命令,它的返回结果里面会显示seconds_behind_master,用于表示当前备库延迟了多少秒。它的计算方法是这样的:
1. 每个事务的binlog 里面都有一个时间字段,用于记录主库上写入的时间;
2. 备库取出当前正在执行的事务的时间字段的值,计算它与当前系统时间的差值,得到seconds_behind_master。可以看到,其实seconds_behind_master这个参数计算的就是T3-T1。所以,我们可以用seconds_behind_master来作为主备延迟的值,这个值的时间精度是秒。
主备延迟的来源
- 备库所在机器的性能要比主库所在的机器性能差。
- 备库的压力大。
- 大事务。如果一个主库上的语句执行10分钟,那这个事务很可能就会导致从库延迟10分钟。如删除太多记录。
- 备库的并行复制能力。这个在下一篇讲解
可靠性优先策略
执行主备切换的时候,它的过程是这样子的:
1. 判断备库B现在的seconds_behind_master,如果小于某个值(比如5秒)继续下一步,否则持续重试这一步;
2. 把主库A改成只读状态,即把readonly设置为true;
3. 判断备库B的seconds_behind_master的值,直到这个值变成0为止;
4. 把备库B改成可读写状态,也就是把readonly 设置为false;
5. 把业务请求切到备库B。
显然,中间会有一段时间,数据库是不可用的。
可用性优先策略
如果采用可用性优先的策略,即马上进行切换,会存在数据不一致的问题。
采用的是mixed的binlog格式
在执行以下语句期间有主备切换。
insert into t(c) values(4);
insert into t(c) values(5);
1. 步骤2中,主库A执行完insert语句,插入了一行数据(4,4),之后开始进行主备切换。
2. 步骤3中,由于主备之间有5秒的延迟,所以备库B还没来得及应用“插入c=4”这个中转日志,就开始接收客户端“插入 c=5”的命令。
3. 步骤4中,备库B插入了一行数据(4,5),并且把这个binlog发给主库A。
4. 步骤5中,备库B执行“插入c=4”这个中转日志,插入了一行数据(5,4)。而直接在备库B执行的“插入c=5”这个语句,传到主库A,就插入了一行新数据(5,5)。
最后的结果就是,主库A和备库B上出现了两行不一致的数据。可以看到,这个数据不一致,是由可用性优先流程导致的。
采用的是row的binlog格式
1. 步骤2中,主库A执行完insert语句,插入了一行数据(4,4),之后开始进行主备切换。
2. 步骤3中,由于主备之间有5秒的延迟,所以备库B还没来得及应用“插入c=4”这个中转日志,就开始接收客户端“插入 c=5”的命令。
3. 步骤4中,备库B插入了一行数据(4,5),并且把这个binlog发给主库A。
4. 步骤5中,备库B执行“插入c=4”这个中转日志,因为row模式中会记录新插入的行的所有字段值,那么插入的就是(4,5),就报主键重复错误,插入失败。