日期:2014-05-16 浏览次数:20959 次
本文的追查过程来源于某次mysql无法正常关闭。
?
1、复现
第一次出现时环境比较复杂,多次试验后发现,如下过程能够稳定复现。
a)????? 系统环境
gcc版本
Using built-in specs.
Target: x86_64-redhat-linux
Configured with: ../configure –prefix=/usr –mandir=/usr/share/man –infodir=/usr/share/info –enable-shared –enable-threads=posix
Thread model: posix
gcc version 4.1.2 20080704 (Red Hat 4.1.2-46)
b)????? 复现过程
安装(使用版本mysql-5.1.45, innodb-plugin1.0.6)
./configure -prefix=/data/mysql5 –with-plugins=partition,heap,innodb_plugin,myisam,myisammrg,csv,example –with-extra-charsets=all –enable-assemble –enable-static? –enable-thread-safe-client |
make && make install |
?
执行
1) >use test;2) >create table t(c int) ENGINE=InnoDB;
? 3) >alter table t add index c(`c`); 4) >quit; 5) #bin/myqladmin –uroot –p shutdown //终端下关闭 |
现象:执行shutdown语句时,输出如下
bin/mysqld_safe: line 137: 15569 Segmentation fault????? nohup /data/mysql5/libexec/mysqld –defaults-file=my.cnf –based1100919 15:53:40 mysqld_safe Number of processes running now: 0100919 15:53:40 mysqld_safe mysqld restarted |
?
说明:正常的执行mysqladmin应该输出如下
100919 15:50:18 mysqld_safe mysqld from pid file /data/mysql5/run/mysqld.pid ended |
?
2、追查
?????? 刚开始以为是代码问题,改用debug模式时发现在执行步骤3)的时候mysqld就dump导致重启了。追查导致dump的代码执行路径如下
add_index –> row_merge_build_indexes?–> row_merge_sort –>?row_merge –>?row_merge_blocks_copy
??? 前两个函数在handler/handler0alter.cc,后面的函数在row/row0merge.c,功能是新建的索引排序并合并到同一个文件中。
?????? 发现dump的点居然是row_merge_blocks_copy函数的传参过程,因此怀疑是内存访问方面的问题。使用valgrind试运行。
在非debug模式下使用valgrind启动mysql,发现在执行shutdown命令时,valgrind有如下输出:
==5998== Thread 16:==5998== Invalid read of size 4==5998==??? at 0×30B560B0F0: pthread_kill (in /lib64/libpthread-2.5.so)==5998==??? by 0×7822A4: thr_alarm (in /home/dingqi/innodb_ssd/mysql/libexec/mysqld)
? ==5998==??? by 0×598E62: my_real_read(st_net*, unsigned long*) (in /home/dingqi/innodb_ssd/mysql/libexec/mysqld) ==5998==??? by 0×599264: my_net_read (in /home/dingqi/innodb_ssd/mysql/libexec/mysqld) ==5998==??? by 0×5AA14E: handle_one_connection (in /home/dingqi/innodb_ssd/mysql/libexec/mysqld) ==5998==??? by 0×30B56062F6: start_thread (in /lib64/libpthread-2.5.so) ==5998==??? by 0×30B4AD1B6C: clone (in /lib64/libc-2.5.so) ==5998==? Address 0×3197D9D0 is on thread 15’s stack |
?
thread 16访问了thread 15的栈空间数据!
3、分析
?????? 这里我们先不考虑两个thread分别是作什么的,但这种错误必然留下隐患。
在手头的其他环境对照试验如下:
环境 | Os & gcc版本 | 结果 |
原环境 | x86_64-redhat-linux
? gcc version 4.1.2 20071124 (Red Hat 4.1.2-42) |
异常 |
对照1 | x86_64-redhat-linux
? gcc version 3.4.6 20060404 (Red Hat 3.4.6-3) |
正常 |
对照2 | Target: i386-redhat-linux
? gcc version 4.1.2 20071124 (Red Hat 4.1.2-42) |
正常 |
手头环境不多,初步认为是: 在64位机器上gcc版本为4.1.2时,会出现如上问题。
?????? 需要查出为什么环境不同造成生成的可执行版本有差异。想到Makefile。
?????? 将不同环境下的Makefile作diff后赫然发现,出问题版本的Makefile有这行
CXXFLAGS =? -O3 ?-fno-implicit-templates -fno-exceptions -fno-rtti 与其他机器不同。
?????? 而这个文件中CFLAGS确是-O2!? 是否