读了rpl_slave.cc:handle_slave_io的源码(Mysql 5.6.11),总结一下
函数概述
handle_slave_io是slave io_thread的主函数,函数逻辑入口为rpl_slave.cc:start_slave_threads
主体结构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
|
一些重点
- 此处不分析锁什么的,因为看不懂
- 4047 设置max_packet_size的目的不明
- 4073 开始slave会向master直接发送一些sql,然后解析返回。而不是包装在某个包的某个字段里,用一些预定义的变量来传递结果。
这种设计一下就觉得山寨起来。
后经同事 @神仙 指点,mysql这样做貌似是为了兼容性,免得数据包格式被改来改去。
(看到mysql里大量的兼容代码都拿来处理包结构的问题,最极品的可能是莫过于LOG_EVENT_MINIMAL_HEADER_LEN了)
在对流量影响不大的情况下,直接用sql反复查询的确是个好的解决手法 - 4250 将master_info和relay log刷到disk上。
先刷relay log,后刷master_info。这样意外的故障可以通过relay log恢复机制来恢复。
若先刷master_info,后刷relay log,意外故障时master_info已经更新,比如(0-100, 100-200),而数据(100-200)丢失,仅有(0-100),恢复的replication会从200开始。整个relay log会成为(0-100, 200-),中间数据会丢失。
start slave时slave向master发送的事件
SELECT UNIX_TIMESTAMP() (rpl_slave.cc:get_master_version_and_clock)
- SHOW VARIABLES LIKE ‘SERVER_ID’ (rpl_slave.cc:get_master_version_and_clock)
- SET @master_heartbeat_period=? (rpl_slave.cc:get_master_version_and_clock)
- SET @master_binlog_checksum= @@global.binlog_checksum (rpl_slave.cc:get_master_version_and_clock)
- SELECT @master_binlog_checksum (rpl_slave.cc:get_master_version_and_clock)
- SELECT @@GLOBAL.GTID_MODE (rpl_slave.cc:get_master_version_and_clock)
SHOW VARIABLES LIKE ‘SERVER_UUID’ (rpl_slave.cc:get_master_uuid)
SET @slave_uuid= ‘%s’(rpl_slave.cc:io_thread_init_commands)
- COM_REGISTER_SLAVE(rpl_slave.cc:register_slave_on_master)
- COM_BINLOG_DUMP(rpl_slave.cc:request_dump)
master与slave的时间差
可以看到slave获得master的时间方法就是直接下sql,完全忽略网络延迟等等等等,属于不精准的时间
这篇文章从源码级别分析了Seconds_Behind_Master的来源,也给出了备库延迟跳跃的原因。总的来说就是Seconds_Behind_Master不可信。