一、主从数据一致性

1.1、如何保证主从数据一致性

参考叶师傅文章:FAQ系列 | 如何保证主从复制数据一致性

在MySQL中,一次事务提交后,需要写undo、写redo、写binlog,写数据文件等等。在这个过程中,可能在某个步骤发生crash,就有可能导致主从数据的不一致。为了避免这种情况,我们需要调整主从上面相关选项配置,确保即便发生crash了,也不能发生主从复制的数据丢失。
MASTER上修改配置
innodb_flush_log_at_trx_commit = 1 --> redo log 1写磁盘、2写系统缓存(操作系统挂可能丢数据)、0写redo log buffer(mysql挂可能丢数据)
sync_binlog = 1 --> binlog 1写磁盘、0写系统缓存
保证每次事务提交后,都能实时刷新到磁盘中,尤其是确保每次事务对应的binlog都能及时刷新到磁盘中
SLAVE上修改配置
master_info_repository = "TABLE"
relay_log_info_repository = "TABLE"
relay_log_recovery = 1
确保在slave上和复制相关的元数据表也采用InnoDB引擎,受到InnoDB事务安全的保护;开启relay-log自动修复机制,发生crash时根据relay_log_info中记录的已执行的binlog位置从master上重新抓取回来再次应用,以此避免部分数据丢失的可能性。

这样配置后,正常情况下主从数据应该是一致的~

1.2、主从数据不一致,复制状态正常

• binlog_format='STATEMENT'
只要复制语句对应的表结构一致,主从数据是否一致不会影响复制状态
• binlog_format='ROW'
1、有主键/唯一索引的情况下,slave应用relay-log的过程只需匹配主键/唯一索引即可,不会考虑其他列与master上的原始值是否一致
2、slave update/delete master上永远不会访问的数据
一致性的保证,需要定期使用pt工具检测并同步啦●-●

二、relay_log_recovery && relay_log_purge

参考文章:MySQL relay_log_purge=0 时的风险

有时候,我们希望将MySQL的relay-log多保留一段时间,比如用于高可用切换后的数据补齐,于是就会设置relay_log_purge=0,禁止SQL_Thread在执行完一个relay-log后自动将其删除。
relay_log_recovery=1 && relay_log_purge=0会有什么坑
• 由于崩溃或停止MySQL时,SQL_Thread可能没有执行完全部的relay-log,最后一个relay-log中的一部分数据会被重新获取到新的文件中。也就是说,这部分数据重复了两次
• 如果SQL_Thread跟得很紧,则可能在IO_Thread写入relay-log,但还没有同步到磁盘时,就已经读取执行了。这时,就会造成新的文件和旧的文件中少了一部分数据

对于复制来说这样不会有什么影响,但如果我们读取relay-log来获取数据,必须注意这一点,否则就会造成数据不一致

三、MHA-Failover可能遇到的坑

传统复制环境,MHA利用Latest Slave的relay-log去补全其他Slave的与Latest Slave之间的差异数据;GTID环境,通过change master to利用binlog补全数据,不再依赖relay-log
为了方便模拟,本文选择手动Failover来检测MHA遇到上面提到的坑会出现什么现象?本文使用MHA-手动Failover流程(传统复制&GTID复制)中的基本环境

3.1、relay-log重复

人为暂停SQL_Thread,再关闭MySQL实例,模拟SQL_Thread没有执行完全部的relay-log

relay_log_recovery=1 && relay_log_purge=0
#测试数据简写如下
Node1写入第一条记录->Node3停止io_thread
Node1写入第二条记录->
    1、Node2从库stop slave sql_thread;
    2、Node1主库写入一条新数据row_new
    3、Node2从库shutdown;
    4、Node2从库启动mysql,start slave;
Node2停止io_thread
Node1写入第三条记录
View Code

相关文章: