- * MHA的整个故障(离线)切换过程-------------------------------------------------------------------------------检测主库的状态,确认是否崩溃。 - 确认服务崩溃,保存binlog,推送到主控机,并可以强制关闭主库避免脑裂。 - 找出数据最新的从库(也就是read_master_log_pos最大的),确定下新主库。 - 从最新从库上生成差异的relaylog,再加上未读取的binlog,应用到新主库,记下偏移。 - (并发)的为其他从库生成差异的relaylog和binlog,应用到各个从库。 - 从库指向新主库的偏移处,开始复制。
- * 源码部分关键逻辑-------------------------------------------------------------------------------**读取配置 * *检查配置 - 检查apply_diff_relay_log的版本号 - 连接所有服务器并读取状态(得知老主库) - 检查参数传进来的崩溃主库是否与老主库地址一致,否则终止切换 - 检查老主库是否在离线主机列表中,不在的话就终止切换 - 检查是否真的连接不上mysql服务 - 检查所有在线从库,是否都指向老主库 - 检查是否有些不该忽略失败的从库已经离线 - 检查上次切换是否失败 - 检查上次切换发生时间与本次切换的时间间隔,太短则终止 - 从所有从库获取"切换锁" - 保证所有从库的slave sql线程已经启动 * *如果支持gtid自动定位但未启用,那么应该强制apply_diff_relay_log禁用log_bin?? * *强制关闭 - (并发)强制停止所有从库的slave io线程 - 探测从主控机到崩溃主库所在主机的ssh可达性 - 执行master_ip_failover_script,保证崩溃主库所在主机的ip失活防脑裂,否则终止切换 - 只要有一个在线从库的salve io线程停止失败,那么就终止切换
- * *探测出复制延迟最小的从库、复制延迟最大的从库 * *根据最新从库的slave io线程的读头,保存老主库的binlog。 - 如果崩溃主库所在主机不可达,那么就会丢失binlog(Read_Master_Log_Pos to the tail) - 如果可达,ssh连接上去,然后执行save_binary_logs--command = save,将保存后的binlog拷贝到主控机,这步称呼read_to_tail。 * *根据最新、最老从库的读头以及某些从库的可忽略失败,来决定哪个从库作为relaylog、binlog补偿的基准 - 如果所有从库的读头一致,跳过 - ssh逐一连接最新从库,执行apply_diff_relay_logs--command = find,看是否realylog包含了最老从库的读头。 - 如果没有用来补偿的基准从库,终止切换 * *选择新主库(新主库不一定是最新从库,参照"在线切换"中的描述) * *恢复新主库 - 若果新主库的读头落后于最新从库,那么ssh连接上最新从库,执行apply_diff_relay_logs--command = generate_and_send,从最新从库的relaylog中提取新主库读头直到最新从库读头处的二进制日志,这步称呼为read_to_latest,
- $latest_slave - >{
- Master_Log_File
- }: $latest_slave - >{
- Read_Master_Log_Pos
- } - 将主控机保存好的最新从库读头到主库binlog尾部的日志(read_to_tail),拷贝到新主库 - 如果不是最新从库或者有保存过read_to_tail,那么就应用差异日志。--首先等待新主库上已经有的relaylog都重放完毕,停止slave sql线程--读取最新复制状态--ssh执行save_binary_logs--command = save,从自身relaylog中恢复exec_to_read--ssh执行apply_diff_relay_logs--command = apply,将前面生成的3部分补偿日志全部导入。 - 执行主控机上的master_ip_failover--command = start脚本,激活新主库的ip。 - 关闭新主库的只读,开启可写模式。 * *恢复所有从库(类似单独恢复主库的过程) - (并发)中继补偿,生成read_to_latest - (并发)将早生成的read_to_tail部分,拷贝到各个从库,应用差异日志,指向新主库,启动复制 - 新主库执行reset slave * MHA(在线)主库切换过程----------------------------------------------------------------------------------------------------------------------------------------------------------------------sudo / usr / bin / masterha_master_switch--master_state = alive--conf = /etc/masterha / app1.cnf--new_master_host = 192.168.128.130--new_master_port = 3309--orig_mast\er_is_new_slave * *识别老主库。 - 读取配置MHA配置文件; - 连接并读取所有的数据库服务状态; - (并发)连接所有从库,看mysql服务是否在运行,如果机器都宕机了,那就终止本次切换。 - 遍历每台从库,获取所有能获取的信息,比如:msyql服务版本号、是否开启了gtid、是否开启了log - bin、是否只读、复制相关系统变量和状态变量。 - 统计服务器信息:离线服务器、在线服务器、在线从库、失败从库等。 - 比较所有从库的mysql服务版本,找出最老和最新的版本。 - 验证当前真正的主库是谁? - 统计在线服务器中的"非从库"(not_slave)标记,只能为1,否则终止本次切换过程。 - 根据从库的指向来找出存在哪些主库(支持3层复制结构(主 - 从 - 从的从))。真正的主库必须是在"线并且可写",如果没有一台主库可写或者存在两台可写,那么终止切换。 - 判断本次切换是否支持gtid。 - 检查所有在线从库上是否有复制账户并有相应的REPLICATION SLAVE权限; - 必要时在老主库上进行flush tables操作; - 从老主库获取"监视锁"; - 从所有从库获取"切换锁"; - 检查所有在线从库的复制健康状况; - 读取当前的复制状态; - 判断是否有问题(IO、SQL线程是否在运行,数据延迟多久) * *识别新主库。 - 识别数据最新的从库; - 比较master_log_file: read_master_log_pos。 - 选择新主库; - 识别优先从库,在线的并带有candidate_master标记。 - 识别应该忽略的从库,带有no_master标记、或者未开启log_bin、或者mysql服务版本不是最老、与最新从库相比数据延迟比较大。 - 选择优先级依次为:优先列表、最新从库列表、所有从库列表,但一定要排除忽略列表。 - 检查新老主库的复制过滤规则是否一致; - Binlog_Do_DB、Binlog_Ignore_DB、Replicate_Do_Table等。
- * *拒绝更新,防止脑裂。 - 调用master_ip_online_change脚本,stop子命令。新主库上,设置为只读;老主库上,禁止会话级别的log_bin、优雅等待所有sql线程退出、设置为只读、 - 必要时,在老主库,锁住所有表,并检查binlog是否已经停止前进。binlog停止前进后,记下偏移位置。 * *重新读取所有在线从库的运行状态。 * *新主库从老主库应用完所有的事件日志。 - 新主库上,执行master_pos_wait,然后记下新主库binlog的file: pos。 - 调用master_ip_online_change脚本,start。新主库上,设置为只读。
- * *(并发)从库应用完老主库所有的事件日志并指向新主库。 - master_pos_wait - change_master_and_start_slave
来源: http://www.cnblogs.com/aware-why/p/5844618.html