
爱可生开源社区出品,原创内容未经授权不得随意使用,转载请联系小编并注明来源。
本文约 700 字,预计阅读需要 2 分钟。
某业务 MySQL 实例(MySQL 5.7.20 社区版)发生 Crash,现需要对其具体原因进行分析。
/mysql/mysql-5.7.20/bin/mysqld(my_print_stacktrace+0x35)[0xf468f5]
/mysql/mysql-5.7.20/bin/mysqld(handle_fatal_signal+0x4a4)[0x7cd434]
/lib64/libpthread.so.0(+0xf100)[0x7f3564112100]
/mysql/mysql-5.7.20/bin/mysqld(_ZN10Field_blob15copy_blob_valueEP11st_mem_root+0x30)[0x7fd160]
/mysql/mysql-5.7.20/bin/mysqld(_Z25mysql_prepare_blob_valuesP3THDR4List14ItemEP11st_mem_root+0x29e)[0xe9901e]
/mysql/mysql-5.7.20/bin/mysqld(_Z12write_recordP3THDP5TABLEP9COPY_INFOS4_+0x212)[0xe995f2]
/mysql/mysql-5.7.20/bin/mysqld(_ZN14Sql_cmd_insert12mysql_insertEP3THDP10TABLE_LIST+0x812)[0xe9a982]
/mysql/mysql-5.7.20/bin/mysqld(_ZN14Sql_cmd_insert7executeEP3THD+0xce)[0xe9b15e]
/mysql/mysql-5.7.20/bin/mysqld(_Z21mysql_execute_commandP3THDb+0xd82)[0xd13b62]
/mysql/mysql-5.7.20/bin/mysqld(_Z11mysql_parseP3THD12Parser_state+0x3a5)[0xd18205]
/mysql/mysql-5.7.20/bin/mysqld(_Z16dispatch_commandP3THDPK8COM_DATA19enum_server_command+0x11bf)[0xd1942f]
根据堆栈打印的信息可以得知,当时 Crash 的时间点 MySQL 正在执行 INSERT 操作,且操作涉及 BLOB 数据类型的数据,在源码执行到 copy_blob_value 函数时触发 Crash。
在本地测试环境中安装同版本 MySQL 实例后,使用 gdb 定位代码具体位置。
gdb ./mysqld
(gdb) b *0x7fd160
Breakpoint 1 at 0x7fd160: file /export/home/pb2/build/sh_0-32013917-1545390211.74/mysql-5.7.25/sql/field.cc, line 3053.
在 https://github.com/mysql/mysql-server/blob/mysql-5.7.25/sql/field.cc 中找到对应行数的源码,在该代码附近没有 BUG 修复记录。
ctrl+f 搜索函数 copy_blob_value,然后点击左边的 ...,之后选择 View git blame,发现有一个 BUG 修复记录。

根据该 BUG 修复记录描述,MySQL 在执行 INSERT ... UPDATE 类型语句时(也就是 INSERT ... ON DUPLICATE ),当 INSERT 操作失败之后(Unique Key 冲突),会执行 UPDATE 操作,而 UPDATE 操作会在 INSERT 的 VALUE() 中找到需要更新的 Old Data。整个流程如下:
INSERT 中的数据或 UPDATE 后的新数据INSERT 失败,进入 UPDATE 流程,找到旧数据
可以看到在找到 Old Data 后,新的指针就会指向这个 Data 内存地址,这时 2 个指针同时指向一个内存地址,此处存在 3 种导致 Crash 的情况:
LHS_FIELD 指向的内存已被释放并重新分配以容纳新数据,将导致空指针问题。LHS_FIELD->ptr 指向的内存未被释放但被重用,并且新数据可以放在相同的内存位置,则更新错误的值。https://bugs.mysql.com/bug.php?id=79243
使用 INSERT ... ON DUPLICATE 语句操作 BLOB 数据类型的列。
INSERT ... ON DUPLICATE 语句操作 BLOB 数据类型的列。本文关键字:#MySQL# #BLOB# #BUG#