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 ...
随机推荐
- ActiveMQ安全机制设置
一.设置后台管理密码a.ActiveMQ使用的是jetty服务器,找到D:\div\apache-activemq-5.11.1\conf\jetty.xml文件: <bean id=" ...
- linux下清空c++ cin无效流的方式
cin.clear(); cin.ignore(10000,'\n');//这里面的参数很重要
- SpringMvc注解开发
1.四大注解的定义 (1)Controller注解:该注解使用在一个类上面,参数为value,值为访问该controller的名称,默认为空,如果为空 则值为该controller类名的首字母小写的值 ...
- SQL更改表架构
修改SQL架构: ALTER SCHEMA 新架构 TRANSFER 旧架构.对象名称
- spring定时任务(@Scheduled注解)
(一)在xml里加入task的命名空间 xmlns:task="http://www.springframework.org/schema/task" http://www.spr ...
- Eclipse中让Scala缩进变为4
Windows->preference->Scala->Editor->Formatter->Spaces to indent
- javax.naming.NamingException: Cannot create resource instance报错修改
//下面内容为网上获取 avax.naming.NamingException: Cannot create resource instance at org.apache.naming.factor ...
- Java基础-内部类介绍
java内部类介绍 内部类一共分为4种 成员内部类 静态内部类 方法内部类 匿名内部类 下面我会为大家详细介绍每一个内部类!! 成员内部类 成员内部类就好像是外部类的一个成员属性,也是内部类中最常见的 ...
- @ConfigurationProperties与@value区别
@ConfigurationProperties与@value区别 @ConfigurationProperties @value 功能 批量注入配置文件中的属性 一个个指定 松散绑定 支持 不支 ...
- mysql安装配置、主从复制配置详解
作者:NiceCui 本文谢绝转载,如需转载需征得作者本人同意,谢谢. 本文链接:http://www.cnblogs.com/NiceCui/p/8213723.html 邮箱:moyi@moyib ...