策略
可靠性优先策略
比如一开始的双M架构,切换过程如下:
- 判断备库B现在的SBM,若小于某值(比如5s)继续下一步,否则持续重试该步
- 把主库A改成只读状态,即把readonly设置为true
- 判断备库B的SBM值,直到该值=0
- 把备库B改成可读写状态:把readonly 设置为false
- 把业务请求切到备库B
切换一般由HA系统完成。
MySQL可靠性优先主备切换流程
该切换流程中有不可用时间。因为在step2后,A、B都readonly,此时系统不可写,直到step5完成后才恢复。
在这个不可用过程,较耗时的是step3,可能耗费几s。这也是为什么要在step1先做判断,确保SBM足够小。
倘若一开始主备延迟就长如30min,而不先做判断直接切换,系统的不可用时间就会长达30min,一般业务都是不能接受的。
系统的不可用时间,是由该数据可靠性优先的策略决定的。也可选择可用性优先的策略,来把这个不可用时间几乎降为0。
可用性优先策略
如果我强行把步骤4、5调整到最开始执行,也就是说不等主备数据同步,直接把连接切到备库B,并且让备库B可以读写,那么系统几乎就没有不可用时间了。
我们把这个切换流程,暂时称作可用性优先流程。这个切换流程的代价,就是可能出现数据不一致的情况。
接下来,我就和你分享一个可用性优先流程产生数据不一致的例子。假设有一个表 t:
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);
初始化数据后,主库和备库上都是3行数据。接下来,业务人员要继续在表t上执行两条插入语句的命令,依次是:
insert into t(c) values(4); insert into t(c) values(5);
假设,现在主库上其他的数据表有大量更新,导致主备延迟达到5s。在插入一条c=4的语句后,发起了主备切换。
可用性优先策略,且binlog_format=mixed时的切换流程和数据结果。
step2:主库A执行完insert,插入了一行数据(4,4),之后开始进行主备切换
step3:由于主备之间5s延迟,所以备库B还没来得及应用“插入c=4”这个中转日志,就开始接收客户端“插入 c=5”的命令
step4:备库B插入数据(4,5),并把该binlog发给主库A
step5:备库B执行“插入c=4”这个中转日志,插入一行数据(5,4)。而直接在备库B执行的“插入c=5”这个语句,传到主库A,就插入一行新数据(5,5)。
最终,A、B上出现两行不一致数据,是由可用性优先流程导致。
若我还是想用可用性优先策略,但设置binlog_format=row,会咋样?
row格式在记录binlog时,会记录新插入的行的所有字段值,所以最后只会有一行不一致。而且两边主备同步的应用线程会报错duplicate key error并停止。即这种情况,B的(5,4)和A的(5,5)这两行数据,都不会被对方执行:
可用性优先策略,且binlog_format=row
所以使用row格式,数据不一致更容易被发现。而使用mixed、statement,数据很可能悄悄地就不一致。若你过很久才发现数据不一致,那可能只能删库跑路了。
主备切换的可用性优先策略会导致数据不一致。所以更推荐使用可靠性优先策略。毕竟对数据服务,数据的可靠性 > 可用性。
有没有哪种情况数据的可用性优先级就是更高呢?
有个库的作用是记录操作日志。这时,若数据不一致,可通过binlog修复,而这短暂不一致也不会引发业务问题。
同时,业务系统依赖于这个日志的写入逻辑,若该库不可写,会导致线上业务操作无法执行。
这时候,你可能需要先强行切换,事后再补数据。
事后复盘,想到个改进措施:让业务逻辑不要依赖于这类日志的写入。即日志写入这个逻辑模块应该可降级,比如写到本地文件或另外一个临时库。
这种场景就可以使用可靠性优先策略了。
按可靠性优先,异常切换会是什么效果?
假设,主库A和备库B间的主备延迟是30min,这时主库A掉电,HA系统要切换B作为主库。在主动切换时,可以等到主备延迟小于5s时,再启动切换,但这时已经别无选择了。
可靠性优先策略,主库不可用
采用可靠性优先策略,必须得等到备库B的SBM=0后,才能切换。但现在比刚刚更严重,并不是系统只读、不可写,而是系统处于完全不可用。因为,主库A掉电后,我们的连接还没有切到备库B。
能否直接切换到备库B,但保持B只读?
不行。因为,这段时间内,中转日志还没有应用完成,若直接发起主备切换,客户端查询看不到之前执行完成的事务,会认为有“数据丢失”。
虽然随着中转日志的继续应用,这些数据会恢复回来,但对于一些业务,查询到“暂时丢失数据的状态”不能被接受。
在满足数据可靠性的前提下,MySQL高可用系统的可用性,依赖于主备延迟。延迟越小,在主库故障时,服务恢复需要时间越短,可用性越高。