MySQL从机持续发生core dump现象

1.   系统环境

CentOS release 6.7

percona-server-5.6.21-70.0(源码编译安装)

 

 

2.   故障简述

主从复制过程中,从机发生core dump

 

3.   故障排查

3.1. 保留现场

保留现场,将备库数据迁移到新的实例中,在新的实例中,复制追赶主库的过程中,仍然会发生core dump现象,也就是说有一个可以稳定复现的环境。

 

3.2. 查看日志

错误日志中记录的core dump信息比较固定,每次sql线程执行到relay log中的位置265796980时,发生core dump,对我们排查问题减少了困难。

 

3.3. 分析core文件

由于可以稳定复现,直接使用gdb在新的环境追查core dump原因,发生core dump时的堆栈信息如下:

Program receivedsignal SIGSEGV, Segmentation fault.

[Switching to Thread 0x7f4434171700(LWP 13995)]

Field_datetime::unpack(this=0x7f3f28011280, to=0x1701 <Address 0x1701 out of bounds>,from=0x7f3f2800d216 "E\336\266wQ\022", param_data=0,low_byte_first=true) at ……

 

 (gdb) bt

#0  Field_datetime::unpack (this=0x7f3f28011280, to=0x1701<Address 0x1701 out of bounds>, from=0x7f3f2800d216"E\336\266wQ\022", param_data=0, low_byte_first=true) at ……

#1  0x00000000008bf649 in unpack_row(rli=<value optimized out>, table=0x7f3f2800d5c0, colcnt=<valueoptimized out>, row_data=0x7f3f2800d203 "", cols=0x7f3f2800d058,

    current_row_end=0x7f3f2800d170,master_reclength=0x7f3f2800d118, row_end=0x7f3f2800d5b4 "") at …..

#2  0x000000000088fa31 in unpack_current_row(this=0x7f3f2800cf00, rli=0x20e85460, overwrite=false) at……

#3  Write_rows_log_event::write_row(this=0x7f3f2800cf00, rli=0x20e85460, overwrite=false) at ……

……

 

分析源码,可以看到发生core dump的源码如下:

Rows_log_event::do_apply_event

| ptr->m_tabledef.compatible_with(thd,const_cast<Relay_log_info*>(rli),

                                             ptr->table, &conv_table,&m_event_mem_root)

    | tmp_table=create_conversion_table(thd, rli, table, mem_root);

| Write_rows_log_event::do_exec_row

    | Write_rows_log_event::write_row

        | unpack_current_row(…..

             | unpack_row(Relay_log_infoconst *rli, TABLE *table,……

                 | conv_field= conv_table ? conv_table->field[field_ptr -begin_ptr] : NULL;

                 | f = conv_field ?conv_field : *field_ptr;

                 |f->unpack(f->ptr,pack_ptr, metadata, TRUE);

                     | Field_datetime::unpack_int64(to,from, low_byte_first);

指针conv_table->field[6]变成了非法地址,访问conv_table->field[6]->ptr发生了访问越界的情况。猜测是由于bug导致conv_table->field[6]由于内存越界被覆盖或者由于内存释放导致了野指针。

3.4. 定位产生问题的操作

结构体conv_table在函数m_tabledef.compatible_with中分配地址空间,在执行行到relay log中的位置265796980发生core dump。

我们使用gdb工具在relay log的位置为265796980时定位到函数Rows_log_event::do_apply_event。

执行操作,设置条件断点:

(gdb)  b  Rows_log_event::do_apply_rowif active_mi->rli->future_event_relay_log_pos==265796980

 

逐步执行操作,观察conv_table->field[6]的变化。发现在与存储引擎交互之后,该变量的值被覆盖了。

Write_rows_log_event::write_row

    | unpack_current_row(rli, &m_cols))                                       coredump 函数

    | while ((error= table->file->ha_write_row(table->record[0])))handle模块,与引擎交互

进一步查看,发生覆盖的地方

ha_write_row

| row_insert_for_mysql

| row_ins_step

    | row_ins_sec_index_entry_low

    ……

       | ut_malloc_nokey

       ….

          | ptr = malloc(total_bytes);

定位原因为malloc申请到的内存地址与变量conv_table->field[6]的内存地址有重叠的地方。

3.5. 重新review代码

查看变量申请内存的源码

ptr->m_tabledef.compatible_with(thd,const_cast<Relay_log_info*>(rli),ptr->table, &conv_table,&m_event_mem_root))

| tmp_table= create_conversion_table(thd, rli, table, mem_root);

    | field_def= (Create_field*) alloc_root(mem_root,sizeof(Create_field));

m_event_mem_root为每个event的内存池,在event执行结束后发生释放,但是conv_table为整个事务的转换表,生命周期要比更长。所以产生了野指针,发生了core dump。

 

4.   总结

如果一个事务内存在两条或者以上的dml语句,并且主库或者从库的表结构存在不一致,同时设置了SLAVE_TYPE_CONVERSIONS,使主从表结构做兼容。那么就有可能发生core dump的现象。

 

……

Query_log_event

Row_log_event1               使用m_event_mem_root为conv_table分配空间

Row_log_event2              m_event_mem_root已经释放,conv_table任然在继续使用

……

 

如上所示,再次访问conv_table时,就可能发生core dump。

5.   修复

官方在版本Percona-Server-5.6.22-71.0修复了此bug,修复详情如下:

https://github.com/percona/percona-server/commit/efc00255d65bc56e9f37e1b3b46603dc4260a8a9

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
在QNX下调试位机(也称为嵌入式系统)的Coredump时,以下是一些基本步骤和工具: 1. 获取Coredump文件:在位机系统出现崩溃或异常时,Coredump文件会自动生成。可以通过以下命令获取Coredump文件:`core_dump_channel`。也可以使用`devc-*`命令检测异常进程并生成Coredump文件。 2. 分析Coredump文件:可以使用GNU调试器(GDB)来分析和调试Coredump文件。可以通过在命令行输入以下命令来启动GDB:`gdb <位机可执行文件> -c <Coredump文件>`。 3. 定位问题代码:在GDB,可以使用`bt`命令来查看函数的堆栈跟踪,以定位造成崩溃的代码。还可以使用`info registers`命令查看寄存器的数值,以了解当前状态。 4. 观察变量和内存:使用GDB,可以使用命令`print`查看变量和内存的值。可以通过打印变量来检查其值是否正确,或者通过查看内存来了解崩溃的原因。 5. 单步调试:可以使用GDB的单步调试功能来逐行执行代码,并观察程序的行为。可以使用`next`命令来执行下一行代码,或者使用`step`命令来进入函数调用。 6. 修改代码和重新编译:在根据Coredump分析找到问题代码后,可以修改代码并重新编译。然后,您可以运行在修复后的代码上的测试,以确保解决了问题。 总之,对于QNX下的位机Coredump调试,主要使用GDB这样的调试工具来分析Coredump文件,查找问题代码,并使用单步调试等功能来定位问题和修复代码。这些步骤可以帮助我们理解和解决嵌入式系统出现的异常和崩溃问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值