MySQL Bug导致异常宕机的分析流程
原文链接:http://click.aliyun.com/m/42521/
摘要: 本文主要通过一个bug来记录一下如何分析一个MySQL bug的崩溃信息。 版本:Percona 5.7.17-11 一、数据库重启日志分析 terminate called after throwing an instance of 'std::out_of_range' what(): ...
本文主要通过一个bug来记录一下如何分析一个MySQL bug的崩溃信息。
版本:Percona 5.7.17-11
一、数据库重启日志分析
terminate called after throwing an instance of 'std::out_of_range' what(): vector::_M_range_check 04:10:09 UTC - mysqld got signal 6 ; mysqld got signal 6 ; ...... Thread pointer: 0x0 Attempting backtrace. You can use the following information to find out where mysqld died. If you see nomessages after this, something went terribly wrong... stack_bottom = 0 thread_stack 0x40000/dbdata/mysql3306/bin/mysqld(my_print_stacktrace+0x35)[0xf3e175] /dbdata/mysql3306/bin/mysqld(handle_fatal_signal+0x4b4)[0x7c3b94] /lib64/libpthread.so.0(+0xf7e0)[0x7f79f28e87e0] /lib64/libc.so.6(gsignal+0x35)[0x7f79f137d495] /lib64/libc.so.6(abort+0x175)[0x7f79f137ec75] /usr/lib64/libstdc++.so.6(_ZN9__gnu_cxx27__verbose_terminate_handlerEv+0x12d)[0x7f79f1c37a8d] /usr/lib64/libstdc++.so.6(+0xbcbe6)[0x7f79f1c35be6] /usr/lib64/libstdc++.so.6(+0xbcc13)[0x7f79f1c35c13] /usr/lib64/libstdc++.so.6(+0xbcd32)[0x7f79f1c35d32] /usr/lib64/libstdc++.so.6(_ZSt20__throw_out_of_rangePKc+0x67)[0x7f79f1bdadb7] /dbdata/mysql3306/bin/mysqld[0x11d8f15] /dbdata/mysql3306/bin/mysqld[0x11d99d5] /dbdata/mysql3306/bin/mysqld(_Z17dict_stats_updateP12dict_table_t23dict_stats_upd_option_t+0x9dc)[0x11de0cc] /dbdata/mysql3306/bin/mysqld(dict_stats_thread+0x4f2)[0x11e0512] /lib64/libpthread.so.0(+0x7aa1)[0x7f79f28e0aa1] /lib64/libc.so.6(clone+0x6d)[0x7f79f1433bcd] You may download the Percona Server operations manual by visitinghttp://www.percona.com/software/percona-server/. You may find information in the manual which will help you identify the cause of the crash.
这部分是数据库崩溃的时候的栈帧,因为收到的是信号6 SIGABRT,只要捕获信号后改变其行为即可。这部分在MySQL官方文档中叫做Stack Trace,参考:
28.5.1.5 Using a Stack Trace
实际上在这里我们已经可以看到大约是统计数据收集的问题,因为我们看到了dict_stats_thread,这是统计收集线程的回调函数。
二、生成更加可视化的Stack Trace
1、通过Stack Trace获得内存地址
获取如下:
[0xf3e175] [0x7c3b94] [0x7f79f28e87e0] [0x7f79f137d495] [0x7f79f137ec75] [0x7f79f1c37a8d] [0x7f79f1c35be6] [0x7f79f1c35c13] [0x7f79f1c35d32] [0x7f79f1bdadb7] [0x11d8f15] [0x11d99d5] [0x11de0cc] [0x11e0512] [0x7f79f28e0aa1] [0x7f79f1433bcd]
2、将这些地址放入一个文件
如:vi /tmp/err0222.log放入即可
3、通nm命令获取库文件链接文件
如:nm -D -n ./mysqld > /tmp/mysqld.sym
4、使用mysql工具resolve_stack_dump得到输出
如下:
[root@dyzsdb2 bin]# ./resolve_stack_dump -s /tmp/mysqld.sym -n /tmp/err0222.log | c++filt 0xf3e175my_print_stacktrace + 53 0x7c3b94 handle_fatal_signal + 1204 0x7f79f28e87e0 _end + -2581151440x7f79f137d495 _end + -280574355 0x7f79f137ec75 _end + -280568243 0x7f79f1c37a8d _end + -2714223630x7f79f1c35be6 _end + -271430210 0x7f79f1c35c13 _end + -271430165 0x7f79f1c35d32 _end + -2714298780x7f79f1bdadb7 _end + -271802481 0x11d8f15 dict_stats_analyze_index_for_n_prefix(dict_index_t*, unsigned long, std::vector<<span class="hljs-keyword" style="box-sizing: border-box; color: rgb(249, 38, 114);">unsigned long, ut_allocator<<span class="hljs-keyword" style="box-sizing: border-box; color: rgb(249, 38, 114);">unsigned long> > const*, n_diff_data_t*, mtr_t*) + 49490x11d99d5 dict_stats_analyze_index(dict_index_t*) + 2693 0x11de0ccdict_stats_update(dict_table_t*, dict_stats_upd_option_t) + 2524 0x11e0512 dict_stats_thread + 1266 0x7f79f28e0aa1 _end + -258147207 0x7f79f1433bcd _end + -279827035
实际上到这里通过函数的调用我们可以发现是统计数据收集出现了问题。
三、通过官方网站查询Bug
在报错信息中提起比较代表性的信息在官方网站中进行搜索通过在percona中查看发现本bug由上游MySQL代码造成BUG号:Bug #84940
并且发现在5.7.18中得到修复同时给出了内部BUG号如下:
[10 Feb 2017 8:12] Shane Bester Oli, Umesh, this would be same as internal: Bug 24585978 - INNODB: ASSERTION TOTAL_RECS > 0 FAILURE IN FILE DICT0STATS.CC
四、查询Bug到底修改了什么地方
这里请教了阿里的印风兄才知道怎么查看,首先拿到了内部bug号:24585978
然后在git的commit log中搜索得到
git --no-pager log >/root/commitlog
vi /root/commitlog 找到commit号为:
29acdaaaeef9afe32b42785f1da3d79d56ed7e59
如下是这个bug的修复地方:
commit 29acdaaaeef9afe32b42785f1da3d79d56ed7e59 Author: Thirunarayanan Balathandayuthapani Date: Wed Feb 8 12:00:52 2017 +0530 Bug #24585978 INNODB: ASSERTION TOTAL_RECS > 0 FAILURE IN FILEDICT0STATS.CC Analysis: ======== There was missing bracket for IF conditon indict_stats_analyze_index_level() and it leads to wrong result. Fix: ==== Fix the IF condition indict_stats_analyze_index_level() so that it satisfied the if condtion only if level is zero. Reviewed-by : Jimmy Yang diff --git a/storage/innobase/dict/dict0stats.cc b/storage/innobase/dict/dict0stats.cc index 3494070..55a2626 100644 --- a/storage/innobase/dict/dict0stats.cc +++ b/storage/innobase/dict/dict0stats.cc @@ -1099,10+1099,10 @@ dict_stats_analyze_index_level( leaf-level delete marks because delete marks on non-leaf level do not make sense. */ - if (level == 0 && srv_stats_include_delete_marked? 0: + if(level == 0 && (srv_stats_include_delete_marked ? 0: rec_get_deleted_flag( rec, - page_is_comp(btr_pcur_get_page(&pcur)))) { + page_is_comp(btr_pcur_get_page(&pcur))))) { if(rec_is_last_on_page && !prev_rec_is_copied
五、为什么这么修改
这里是我的浅显的分析,不对的地方的还请见谅。
我们发现这里实际上修改就是多了一个括号而已,但是意义是相当重要的。
if (level == 0 && srv_stats_include_delete_marked ? 0: rec_get_deleted_flag( rec, page_is_comp(btr_pcur_get_page(&pcur)))) 修改为了 if (level == 0 && (srv_stats_include_delete_marked ? 0: rec_get_deleted_flag( rec, page_is_comp(btr_pcur_get_page(&pcur)))))
修改前:
如果level != 0 不管innodb_stats_include_delete_marked参数如何设置必然触发判断是否存在del_flag,然后通过设置偏移量的方式 跳过这行,但是随后的(*total_recs)++; 将不会触发,极端情况下可能为0。
而在上层代码dict_stats_analyze_index中的found_level:地方实际上是需要非叶子结点行数不为0的如下:
ut_ad(total_recs > 0); ut_ad(n_diff_on_level[n_prefix - 1] > 0);
六、如何规避
在官网查看的时候有如下方式可以规避这个Bug
- 升级到5.7.18
- 设置参数
innodb-stats-persistent = 0 innodb-stats-transient-sample-pages = 20 innodb-stats-auto-recalc = 0
设置这些参数后实际上是使用的老的非固化的统计数据收集的方式,而不会通过线程dict_stats_thread收集下面是逻辑片段位于row_update_statistics_if_needed中如下:
if (dict_stats_is_persistent_enabled(table)) { //参数innodb-stats-persistent 作用 if (counter > n_rows / 10 && dict_stats_auto_recalc_is_enabled(table)) {//参数innodb-stats-auto-recalc 作用dict_stats_recalc_pool_add(table); table->stat_modified_counter = 0; } return; } if (counter > 16+ n_rows / 16 ) { ut_ad(!mutex_own(&dict_sys->mutex)); dict_stats_update(table, DICT_STATS_RECALC_TRANSIENT); }
这样做的话肯定不会调用到触发bug的函数,有兴趣的可以看看dict_stats_update(table, DICT_STATS_RECALC_TRANSIENT);的逻辑。实际上使用的是老的方式断点可以打在btr_estimate_number_of_different_key_vals函数上。
MySQL Bug导致异常宕机的分析流程的更多相关文章
- ASMB的BUG(ORA-04030 kfmditer)导致数据库宕机
ASMB的BUG(ORA-04030 kfmditer)导致数据库宕机 现象: 客户的一个重要生产系统RAC的一个实例宕机,查看alert日志: Fri Jun 21 17:05:52 2013 Er ...
- 记-ItextPDF+freemaker 生成PDF文件---导致服务宕机
摘要:已经上线的项目,出现服务挂掉的情况. 介绍:该服务是专门做打印的,业务需求是生成PDF文件进行页面预览,主要是使用ItextPDF+freemaker技术生成一系列PDF文件,其中生成流程有:解 ...
- ORA-04031错误导致宕机案例分析
今天遇到一起ORACLE数据库宕机案例,下面是对这起数据库宕机案例的原因进行分析.解读.分析过程中顺便记录一下这个案例的前因后果,攒点经验值,培养一下分析.解决问题的能力. 案例环境: 操作系统 ...
- mysql 异常宕机 ..InnoDB: Database page corruption on disk or a failed,,InnoDB: file read of page 8.
mysql 测试环境异常宕机 系统:\nKylin 3.3 mysql版本:5.6.15--yum安装,麒麟提供的yum源数据库版本 error日志 181218 09:38:52 mysqld_sa ...
- MySQL - 高可用性:少宕机即高可用?
我们之前了解了复制.扩展性,接下来就让我们来了解可用性.归根到底,高可用性就意味着 "更少的宕机时间". 老规矩,讨论一个名词,首先要给它下个定义,那么什么是可用性? 1 什么是可 ...
- 关于mysql主从架构master宕机后,请求转移问题解决办法
mysql架构:一主一从 问题一:有两台mysql数据库,已做好主从.如果运行某一天master服务器mysql故障导致前端请求无法处理怎么办? 答:将前端需要数据库处理的请求转移到slave机上. ...
- 由于某IP大频率提交评论导致服务器宕机
早上突然收到dnspod的宕机通知(好久没收到了,有点手足无措). 服务器在上午10:40时达到85%.uptime显示cpu利用率达到35.不宕才怪. 按照之前的经验,应该是触发一个特别耗CPU的处 ...
- MySQL定时检查是否宕机并邮件通知
我们有时候需要一些检查MySQL是否宕机,如果宕机了应自动重新启动应用并通知运维人员!此脚本用来简单的实现MySQL宕机后自动重启并邮件通知运维,此为SHELL脚本,当然也有一些朋友喜欢用Python ...
- Solr4.8.0源码分析(26)之Recovery失败造成的宕机原因分析
最近在公司做SolrCloud的容灾测试,刚好碰到了一个比较蛋疼的问题,跟SolrCloud的Recovery和leader选举有关,正好拿出来分析下. 现象是这样的:比如我有一台3个shard的So ...
随机推荐
- linux文件 面试知识
1. 文件存储结构 Linux正统的文件系统(如ext2.ext3)中,一个文件由目录项.inode和数据块组成. 目录项:包括文件名和inode节点号. inode:又称文件索引节点, ...
- 修改ASP.NET文件上传大小限制
转自:http://www.hello-code.com/blog/asp.net/201603/5954.html 要点: 1.web.config中的<httpRuntime maxRequ ...
- TCP连接、Http连接与Socket连接
1.TCP连接 手机能够使用联网功能是因为手机底层实现了TCP/IP协议,可以使手机终端通过无线网络建立TCP连接.TCP协议可以对上层网络提供接口,使上层网络数据的传输建立在“无差别”的网络之上. ...
- Polymorphic form--多态表单
一个ruby on rails项目,用户和公司的模型都有地址. 我要创建一个地址表,包含用户和公司表的引用,比直接做下去要好一点,这回让我的数据库设计保持干净. 我的第一印象是,这似乎很难实现,外面所 ...
- Spring IOC(DI)
软件152 余建强 1 什么是IOC IOC—Inversion of Control,即“控制反转”,不是什么技术,而是一种设计思想.在Java开发中,Ioc意味着将你设计好的对象交给容器控制,而不 ...
- 安装 wordpress 出现 抱歉,我不能写入wp-config.php文件
本文告诉大家如何安装 wordpress ,在安装过程出现 抱歉,我不能写入wp-config.php文件如何解决 下载 wordpress China 简体中文 - WordPress 安装 在安装 ...
- Struts2和MVC的简单整合
1.首先还是创建一个简单Maven的项目,导入jar包, <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:x ...
- winform绑定多张图片
开发winform程序的时候经常设计到要显示多张图片的问题,其解决思路一般是先遍历文件夹中的所有图片,然后再把这些图片添加到ImageList控件中,最后再绑定显示出来.这里我们介绍两种绑定的方法: ...
- [javaSE] 并发编程(线程间通信)
新建一个资源类Resource 定义成员变量String name 定义成员变量int age 新建一个输入类Input,实现Runnable接口 定义一个构造方法Input(),传入参数:Resou ...
- 532 -数组中的K-diff对
例1: 输入: [3,1,4,1,5],k = 2 输出: 2 说明:阵列中有两个2-diff对,(1,3)和(3,5). 虽然我们在输入中有两个1,但我们应该只返回唯一对的数量. 例2: 输入: ...