扫二维码与项目经理沟通
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流
先前碰到一个故障,于是引入了crash-safe replication,下面仔细描述;
故障描述:
从库(slave端)宕机,重启后,mysql同步发现有数据主键冲突;
故障分析:
从库宕机后,从库的mysql服务遭到非正常退出,部分数据可能未刷新到磁盘;但这个案例是已经有数据刷新到磁盘了.重启后,从库又重新从主库拉取了这部分数据,再次进行了应用,所以导致数据冲突了.所以接下来就要分析主从相关的一些参数了;
先说说,主从同步的那点事儿.
所谓主从同步,就是主库在生成binlog后,从库拉取主库的binlog,然后将数据应用到从库的过程;
同步分为半同步和异步同步.这个案例是异步,半同步就不细说了.异步同步是指,在主库生成binlog后,从库拉取主库的binlog应用到从库本机的过程;
那这里就要重点介绍几个名词信息了:
IO_thread
SQL_thread
master-info.log
relay-info.log
IO_tread和SQL_thread,经常搭建主从的同学都知道,这是从库上面用于同步的两个关键线程(show processlist可以看到);
master-info.log和relay-info.log是记录从库同步位置和状态等一些信息.
来看下这几个名词间的联系:
从主库生成binlog开始,从库拉取binlog到本机,传输完成后,IO_thread会将拉取到的binlog的文件名及事务位置(postion和gtid)记录到master-info.log,同时,SQL_thread会将拉取到的binlog应用到本地,应用完成后会将完成的binlog文件名和事务位置(postion和gtid)写入到relay-info.log.
这是整个的同步过程.(注意:这两个文件记录的binlog相关信息都是主库的信息,从库的binlog是不会记录到这两个文件的.)
这个过程有两点需要注意:
1.在默认配置的情况下,master-info.log和relay-info.log文件系统层面完成写入操作的.也就是说mysql在将更改信息完成后提交给OS的缓存,什么时候刷盘是由OS决定的.
2.如果从库宕机,重启后,会去读取master-info.log的位置信息.5.6后启用了relay_log_recovery参数,将读取relay-info.log的位置,而不读取master-info.log;
那么结合这个案例,我们就很清晰的知道问题出在哪了.
1.IO_thread拉取完数据,master_info的更改信息在OS的缓存里,还未更改文件,同时,SQL_thread已经应用完数据,这个时候宕机了.那就造成了,master-info.log未更新,但数据库已经将数据写入了.重启后,IO_thread根据未更新的master-info.log重新拉取了重复的数据.
2.在启用了relay_log_recovery后,重启从库后读取的是relay-info.log文件,跟上面情况类似,也是未更新到relay-info.log,然后重新应用了.
3.sync_relay_log和master_relay_log参数为1,这种情况会丢失最后一个事务.导致最后同步的一个事务冲突.
解决方法:
查看冲突数据是否一致,要么在从库删除该数据,让从库重新应用,要么就跳过该错误,继续同步,具体方法不累述,网上大把大把的案例.
总结:
主从异步同步,很多场景都会用到,主从不同步也是经常发生.好在mysql一直在不断的进步,修改.到mysql5.7,主从架构已经相当成熟了.你要相信,你踩到的坑,肯定有很多前辈已经踩过很多次了,所以,放心大胆的用吧.为了让大家少掉坑,我总结下使用异步同步的一些参数设置和一些坑.
主库:1.binlog_format=row 能选用row格式,其他两种就别考虑了,具体的坑太多了.
2.sync_binlog=1,innodb_flush_log_at_trx_commit=1 不要问我为什么.安全是数据库的唯一标准.
3.log_bin_trust_function_creators =1 这个开一下吧,备用,万一被那个二货给改了binlog行模式勒.
4.binlog_rows_query_log_events =1 这个挺有用的,记录sql,row格式下,看binlog是挺不好看的.有这参数,杠杠的.
从库:master-info-repository=table
relay-log-info-repository=table 改成table吧... SQL_thread会吧更改relay-log-info放到应用事务的同一个事务里面,这样就实现了事务与日志修改的原子性了
relay_log_recovery = 1 读的是relay-info的信息,而且会把未执行的relay-log给删掉,重新拉取.
sync_relay_log_info=1 这个,如果relay-info为table的话,可用可不用.如果是file,加个保险吧.
sync_master_info=1 能保证master-info的一致性.
crash-safe 不管是主库还是从库,都挺蛋疼的.上面主要讲的还是crash-safe replication的一些参数.总之保证安全的前提下,在去提升效率吧.如果你觉得可以牺牲安全来保证效率,那就忽略吧.
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流