记MySQL的一次启动异常

9 篇文章 0 订阅
6 篇文章 0 订阅

1.背景

测试环境一直运行良好的MySQL突然莫名挂掉,登上机器重新启动,居然没启动起来

2.寻找原因

尝试一: 查找问题最简单的方法当然是先看日志报错:
图1
如图1所示MySQL启动异常系命中了红框内的断言错误所致,根据那行代码大概猜测可能是buf的长度不够导致的异常。这时候接着往下看,发现MySql提示要保证系统内存满足如下大小:

key_buffer_size + (read_buffer_size + sort_buffer_size)*max_threads = 68255 K

故查看系统所剩内存发现还有10G可用空间,远远超过MySQL所需的65M大小

尝试二:到这里错误日志已基本分析完毕,已没有什么可供继续排查的线索了,此时只有祭出源码调试大法了

(1)启动gdb调试MySQL

gdb -q /usr/local/mysql/bin/mysqld

(2)根据图1的报错位置设置断点并启动程序

(gdb) b log0log.cc:1105
Breakpoint 1 at 0x19ab4bd: file /data/home/jessemiao/install/mysql-5.7.19/storage/innobase/log/log0log.cc, line 1105.
(gdb) r
Starting program: /usr/local/mysql/bin/mysqld

(3)打印当前堆栈,瞬间发现造成断言错误的元凶
图2
堆栈信息中最上层函数参数pad_len=0、len=1024,结合断言错误assertion可知pad_len值异常导致了程序异常。此时我们需要寻找元凶pad_len的来处
(4)寻找元凶pad_len的来处,根据堆栈信息很容易找到log_write_up_to函数
该函数涉及到排查问题的关键代码如下:
图3
如图3所示粉色框住的函数则为发生断言错误所在的函数,其上方红色框住的即为断言错误的元凶。可以发现pad_size初始定义为0,只有俩处地方需要修改其值,而要修改其值则要满足条件判断:

end_offset_in_unit > 0 && (area_end - area_start) > end_offset_in_unit

根据打印各个变量的值发现是图3绿色框部分的end_offset_in_unit变量为0导致修改pad_size的条件不成立。而end_offset_in_unit值则为:

end_offset_in_unit = (ulint) (end_offset % write_ahead_size); 

根据gdb打印变量套用上述表达式:end_offset_in_unit = 16777216 % 8192 = 0
end_offset_in_unit(根据end_offset、end_offset_in_unit表达式变量名猜测end_offset_in_unit为在某块写block上的偏移位置)值为0很正常(1/8192的概率),但是它为0了就会使断言错误的直接凶手pad_size不能得到有效值进而引发MySQL启动异常。

3.解决问题

既然知道了是某个变量在任意block偏移位置为0导致的MySQL启动异常(概率为1/8192),难道这么大的bug刚好被我遇到了?那么问题如何解决?

这时候突然发现图3中pad_size变量传参时居然是条件编译:
图4
根据图四可猜测出pad_size只有在debug模式下才会传参给断言错误所在的函数。那么将当前MySQL bin替换成非debug模式的bin是否就能解决问题?

于是根据当前MySQL版本源码进行重新编译,在cmake时不加-DCMAKE_BUILD_TYPE=Debug选项,使用编译出的bin再次启动MySQL,果然启动成功了。

问题得到解决,猜测问题原因可能是MySQL debug模式下的一个不严谨的小bug(1/8192概率出现)

4.总结

在遇到开源组件异常时,如果根据日志无法找到解决异常的蛛丝马迹时,不妨大胆的去调试源码。源码才是凶案的第一现场,即使我们看不懂大部分内容,但只要抓住源码里涉及异常的核心点,相信总归会得到一些有价值的帮助。

MySQL Slave库恢复是指在主从复制的环境下,当从库出现异常或数据丢失时,需要将从库数据恢复到与主库一致的状态。下面是一次MySQL Slave库恢复的实战录,供参考: 1. 确认从库数据丢失或异常情况 在主从复制的环境下,当从库出现异常或数据丢失时,需要先确认是从库数据丢失还是复制链路中出现问题。 可以通过以下方式进行确认: - 在从库上执行 SHOW SLAVE STATUS 命令,查看 Slave_IO_Running 和 Slave_SQL_Running 的状态,如果其中任意一个为 NO,则说明复制链路出现了问题; - 在从库上执行 SELECT COUNT(*) FROM 表名 命令,查看数据是否与主库一致,如果不一致,则说明从库数据出现了异常或数据丢失。 2. 确认主库数据一致性 在从库数据出现异常或数据丢失之前,需要先确认主库数据是否一致,可以通过以下方式进行确认: - 在主库上执行 SELECT COUNT(*) FROM 表名 命令,查看数据数量与从库是否一致; - 在主库上执行 SHOW MASTER STATUS 命令,查看 File 和 Position 的值。 如果主库数据不一致或者无法确认主库 File 和 Position 的值,则需要先进行主库数据修复。 3. 停止从库复制 在从库数据出现异常或数据丢失后,需要先停止从库复制,可以执行 STOP SLAVE 命令。 4. 备份主库数据 在进行从库恢复前,需要先对主库进行备份,可以通过以下方式进行备份: - 执行 mysqldump 命令备份主库数据; - 将主库数据目录进行复制备份。 5. 恢复从库数据 在备份主库数据后,需要将备份数据恢复到从库中,可以通过以下方式进行恢复: - 执行 mysql 命令将备份数据导入到从库中; - 将备份数据目录进行复制恢复。 6. 启动从库复制 在恢复从库数据后,需要启动从库复制,可以执行 START SLAVE 命令。 7. 确认从库数据一致性 在从库复制成功后,需要再次确认从库数据是否与主库一致,可以通过以下方式进行确认: - 在从库上执行 SELECT COUNT(*) FROM 表名 命令,查看数据数量与主库是否一致; - 在从库上执行 SHOW SLAVE STATUS 命令,查看 Slave_IO_Running 和 Slave_SQL_Running 的状态是否正常。 以上就是一次MySQL Slave库恢复的实战录,希望对你有所帮助。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值