一招教你如何修复MySQL slave中继日志损坏问题
【摘要】MySQL的Crash safe slave是指slave crash后,把slave重新拉起来可以继续从Master进行复制,不会出现复制错误也不会出现数据不一致。
PS:华为云数据库特惠专场钜惠来袭,全场10元起购,直降108000元!新购满额送P30 Pro,点此抢购。
Contents
1 背景
2 Relay log的获取与应用
2.1 源码分析
2.1.1 配置参数relay_log_recovery=OFF重启后,slave机制与源码
2.1.2 配置参数relay_log_recovery=ON重启后,slave机制与源码
3 修复计划
3.1 具体实现思路
3.2 流程图
4 总结
1 背景
MySQL的Crash safe slave是指slave crash后,把slave重新拉起来可以继续从Master进行复制,不会出现复制错误也不会出现数据不一致。为保证crash safe slave,需解决由于未同步刷盘导致的binlog文件接收位置和实际不一致或者relay log文件不完整的问题,因此relay_log_recovery为ON是必需配置参数之一。但是设置relay_log_recovery为ON会导致MySQL正常重启或者宕机恢复时以备库的SQL线程执行位置为起点重新向主库请求binlog,可能由于之前主备时延大,请求点的binlog已被主机清除,最终导致主备复制关系异常,因此设置relay_log_recovery为OFF是生产环境常见的设置。但是,此设置在OS的oom-killer事件以及OS异常断电等情况可能导致备库relay log的部分event不完整, MySQL重启后,SQL线程回放执行到不完整的event就会导致主备复制关系中断,查看error.log可以看到类似如下的错误信息:
2 Relay log的获取与应用
MySQL支持的复制方式按连接协议来区分,可以分为
• 非GTID模式,通过binlog文件名和文件的偏移来决定复制位点信息
• GTID模式,通过GTID信息来决定复制位点信息
2.1 源码分析
2.1.1 配置参数relay_log_recovery=OFF重启后,slave机制与源码
1)基于binlog复制(非GTID)模式,MySQL重启后,重连主库时,备库的IO线程读取slave_master_info表记录的master_log_name以及master_log_pos值向主库请求binlog。
1. |-init_slave()
2. /* read all the slave repositories on disk (either in FILE or TABLE form) and create corresponding slave info objects
3. */
4. |-Rpl_info_factory::create_slave_info_objects
5. |-load_mi_and_rli_from_repositories
6. |-Master_info::mi_init_info()
7. /* Creates or reads information from the repository, initializing the Master_info.*/
8. |-Master_info::read_info()
9. |-get_info()
10. //初始化mi master_log_pos && master_log_name
备库的SQL线程读取slave_relay_log_info表记录的relay_log_name以及relay_log_pos值开始应用relay log。
1. |-init_slave()
2. |-Rpl_info_factory::create_slave_info_objects
3. |-load_mi_and_rli_from_repositories
4. |-Relay_log_info::rli_init_info
5. |-Relay_log_info::read_info()
6. //rli group_relay_log_pos && group_master_log_pos &&
7. group_relay_log_name && group_master_log_name
2)基于GTID复制模式,MySQL重启后,重连主库时,备库的IO线程通过读取mysql.gtid_executed表以及binlog文件获取Executed_Gtid_Set,通过读取realy_log文件获取Retrieved_Gtid_Set,并将两者的并集发送到主库请求binlog。
1. mysqld_main ()
2. //读持久化介质mysql.gtid_executed表
3. |-Gtid_state::read_gtid_executed_from_table ()
4. //读持久化介质binlog
5. |-MYSQL_BIN_LOG::init_gtid_sets ()
6. |-init_slave ()
7. |-Rpl_info_factory::create_slave_info_objects ()
8. |-load_mi_and_rli_from_repositories ()
9. |-Relay_log_info::rli_init_info ()
10. |-MYSQL_BIN_LOG::init_gtid_sets ()
11. |-Relay_log_info::init_relay_log_pos ()
对于备库的SQL线程其应用relay log的起始从slave_relay_log_info表读取,其执行过程如果发现事务的gtid已经存在,则ev->apply_event时就会忽略这个事务,保证不会重复执行同一个事务。
2.1.2 配置参数relay_log_recovery=ON重启后,slave机制与源码
当参数relay_log_recovery为ON,不论是单线程还是多线程回放,MySQL正常重启或者宕机恢复时以备库的SQL线程执行位置为起点重新向主库请求binlog。基于binlog复制发送的是slave_relay_log_info表读取relay_log_name以及Relay_log_pos值。基于GTID复制模式发送的是备库执行完的gtid_sets。
1. static void recover_relay_log(Master_info *mi)
2. {
3. Relay_log_info *rli=mi->rli;
4. // Set Receiver Thread's positions as per the recovered Applier Thread.
5. mi->set_master_log_pos(max<ulonglong>(BIN_LOG_HEADER_SIZE,
6. rli->get_group_master_log_pos()));
7. mi->set_master_log_name(rli->get_group_master_log_name());
8. rli->set_group_relay_log_name(rli->relay_log.get_log_fname());
9. rli->set_event_relay_log_name(rli->relay_log.get_log_fname());
10. rli->set_group_relay_log_pos(BIN_LOG_HEADER_SIZE);
11. rli->set_event_relay_log_pos(BIN_LOG_HEADER_SIZE);
12. }
3 修复计划
当备库配置master_info_repository与relay_log_info_repository都为TABLE时,对于SQL线程而言,会在一个事务提交的同时更新表slave_relay_log_info,其得到原子性保证,即SQL线程执行位置始终是对的。但异常宕机可能导致丢失master info,IO线程会dump到重复的日志和SQL线程可能会重复执行同一个事务,这样就会导致主备复制出错,这样对于非gtid复制的模式,所以为保证主备正常且数据一致,relay_log_recovery=ON为Crash safe slave必需参数。
但是如果开启了gtid就可以避免上述问题,GTID复制协议保证了数据的一致性,且ev->apply_event时会忽略已执行的事务。因此对于备库设置为relay_log_recovery=OFF的配置,relay log文件中可能存在的损坏的event可直接清除,避免出现主备复制关系异常。
3.1 具体实现思路
方案:
1、在MySQL启动初始化过程中进行损坏relay log(不完整event)修复。
2、在初始化Gtid_sets的MYSQL_BIN_LOG:init_gtid_set()处,若配置参数设置了功能启动开关rds_recovery_relay_log=ON,则进入下面流程。
3、扫描relay log时,判断其是否是正常关闭,非正常关闭则进入修复检测流程。
4、读取非正常关闭relay log文件,遍历其event,并记录更新合法的event的位置,若存在非完整event则退出,返回记录的最新合法event位置。
4、根据返回的合法event位置截断relay log,清除文件中损坏的部分。
5、后续流程正常进行
3.2 流程图
4 总结
设置rds_relay_log_recovery参数设置为ON,可解决OS宕机等情况导致MySQL备库的relay log的不完整导致主备异常情况。建议使用方法,在OS宕机等情况,重启mysql服务时,设置开启rds_relay_log_recovery=ON,可预防relay_log_recovery=ON的潜在缺点即自sql thread执行完的gtid起请求的binlog已被master purge。
最后,华为云数据库特惠专场钜惠来袭,比自建好用还省钱,全场10元起购,直降108000元,新购满额送P30 Pro,点此抢购。
一招教你如何修复MySQL slave中继日志损坏问题的更多相关文章
- 17.2.2.1 The Slave Relay Log Slave中继日志
17.2.2.1 The Slave Relay Log Slave中继日志 中继日志, 像binary log,有一组文件组成包含events 描述数据库的修改,和一个index文件包含所有使用过的 ...
- shell脚本修复MySQL主从同步
发布:thebaby 来源:net [大 中 小] 分享一例shell脚本,用于修改mysql的主从同步问题,有需要的朋友参考下吧. 一个可以修改mysql主从同步的shell脚本. 例子 ...
- 使用Innobackupex快速搭建(修复)MySQL主从架构
MySQL的主从搭建大家有很多种方式,传统的mysqldump方式是很多人的选择之一.但对于较大的数据库则该方式并非理想的选择.使用Xtrabackup可以快速轻松的构建或修复mysql主从架构.本文 ...
- 【故障处理】mysql出现大量slave bin日志,将磁盘空间占满
master服务器IO线程 NO 问题描述:造成大量slave bin 日志 大量占用磁盘 排查解决步骤: 1.检查是配置的问题还是mysql数据库本身的故障 2.将master的机器 mysql_ ...
- 处理一则MySQL Slave环境出现ERROR 1201 (HY000): Could not initialize master info structure的案例
mysql> start slave; ERROR (HY000): Slave failed to initialize relay log info structure from the r ...
- Mysql slave 同步错误解决
涉及知识点 mysql 主从同步 ,参考: MySQL数据库设置主从同步 mysqlbin log查看, 参考:MySQL的binlog日志 解决slave报错, 参考: Backup stopped ...
- MySQL数据表修复, 如何修复MySQL数据库(MyISAM / InnoDB)
常用的Mysql数据库修复方法有下面3种: 1. mysql原生SQL命令: repair 即执行REPAIR TABLE SQL语句 语法:REPAIR TABLE tablename[,table ...
- canal mysql slave
[mysqld] log-bin=mysql-bin #添加这一行就ok binlog-format=ROW #选择row模式 server_id=1 #配置mysql replaction需要定义, ...
- 乌龙之MySQL slave IO status:connecting
搭建了一个主从,状态一直如下: 检查错误日志报错如下: review搭建过程,语法并没有问题. 检查用户及网络,也没有问题: so?what is the cause ? 等等....貌似上面搭建用的 ...
随机推荐
- NOIP模拟 17
这次.. 考场刚了T1T2两题的正解 然后T2A了,T1被毒瘤卡常 让skyh得了rank1,QMQ 话说这次考试体(r)验(p)极(yong)佳(jin) 也许是昨晚没玩狼人杀睡的比较好?(现场%苗 ...
- js基础总结02--字符串操作
1.字符串中对单个字符位置的操作 indexOf(char); 从左往右查找,返回匹配到的第一个字符的位置,没有匹配则返回-1 lastiIndexOf(char); 从右往左查找,返回匹配到的第一个 ...
- 2、linux基础-面试题
自己写的答案 1.1GB 2.4 3.ubuntu.dbian.Fedora 4.系统.硬件.clock -w 5.文件 6.uname -a 7.centos是redhat的社区版,redhat是商 ...
- Apache安装问题:APR not found
资料来源:Apache遇到的问题:APR not found 安装apache时出现arp错误问题 按照以上文章试验之后整理如下: #./configure --prefix……检查编辑环境时出现: ...
- 解析XML数据,必看
xml源文件 <?xml version="1.0" encoding="UTF-8"?> <humans> <zhangying ...
- [LC]643题 Maximum Average Subarray I(子数组最大平均数 I)
①英文题目 Given an array consisting of n integers, find the contiguous subarray of given length k that h ...
- Hadoop压缩的图文教程
近期由于Hadoop集群机器硬盘资源紧张,有需求让把 Hadoop 集群上的历史数据进行下压缩,开始从网上查找的都是关于各种压缩机制的对比,很少有关于怎么压缩的教程(我没找到..),再此特记录下本次压 ...
- 分组取topN
假设有这样一个文件,文件内容如下 class1 class2 class1 class1 class2 class2 class1 class2 class1 class2 要求按照班级分组取出每个班 ...
- go中的关键字-defer
1. defer的使用 defer 延迟调用.我们先来看一下,有defer关键字的代码执行顺序: func main() { defer func() { fmt.Println("1号输出 ...
- 领扣(LeetCode)N叉树的层序遍历 个人题解
给定一个 N 叉树,返回其节点值的层序遍历. (即从左到右,逐层遍历). 例如,给定一个 3叉树 : 返回其层序遍历: [ [1], [3,2,4], [5,6] ] 说明: 树的深度不会超过 100 ...