首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >一次DDL引发的数据库异常关闭

一次DDL引发的数据库异常关闭

原创
作者头像
薛晓刚-
修改2025-12-03 11:37:07
修改2025-12-03 11:37:07
140
举报

接到别人求助:有个数据库重启了看看是什么原因?

  • 我现在一般都是处理应用开发问题,很少遇到数据库重启的问题了。
  • 日志发过来,我一看是MySQL。
  • 我已经多年没有遇到过这种了。最后一次处理这样的问题还是2019年。当时系统是由于应用程序的问题也遇到过DDL时候数据库实例关闭。
  • 不过有些系统哪怕没有DDL也会造成数据库实例关闭。有人说是bug,我个人不这么认为。哪有那么多bug?
  • 我认为重现的才能说是bug,比如update id=1的数据,结果改了id=2的数据。这算是逻辑bug吧。几乎没见过这种,如果有,那么应该去修复这个bug。
  • 那么另外一种就是性能引起的。我个人觉得这不算bug。规避就可以了。仅代表个人观点。
  • 因为在大量低效SQL冲击下,数据库会发生OOM、hang住或者无响应、以及实例崩溃等各种问题,这算不算bug呢?

具体出错日志

  • 我这里拿到日志一看就知道问题了。
  • 2025-12-01T18:02:11.466876+08:00 12263058 [ERROR] [MY-013183] [InnoDB] Assertion failure: dict0dict.cc:1885:table->get_ref_count() == 0 thread 140302437545728
  • 其实看到这里我就知道是怎么回事了。

InnoDB: We intentionally generate a memory trap. InnoDB: Submit a detailed bug report to http://bugs.mysql.com. InnoDB: If you get repeated assertion failures or crashes, even InnoDB: immediately after the mysqld startup, there may be InnoDB: corruption in the InnoDB tablespace. Please refer to InnoDB: http://dev.mysql.com/doc/refman/8.0/en/forcing-innodb-recovery.html InnoDB: about forcing recovery. 10:02:11 UTC - mysqld got signal 6 ; Most likely, you have hit a bug, but this error can also be caused by malfunctioning hardware. Thread pointer: 0x7f99ec191670 Attempting backtrace. You can use the following information to find out where mysqld died. If you see no messages after this, something went terribly wrong… stack_bottom = 7f9ab4f36c70 thread_stack 0x46000 /usr/sbin/mysqld(my_print_stacktrace(unsigned char const*, unsigned long)+0x3d) [0x2194f3d] /usr/sbin/mysqld(handle_fatal_signal+0x313) [0xff55f3] /lib64/libpthread.so.0(+0xf630) [0x7f9efd1ab630] /lib64/libc.so.6(gsignal+0x37) [0x7f9efb4c1387] /lib64/libc.so.6(abort+0x148) [0x7f9efb4c2a78] /usr/sbin/mysqld() [0xd5b5df] /usr/sbin/mysqld() [0x2591670] /usr/sbin/mysqld(dict_partitioned_table_remove_from_cache(char const*)+0xe3) [0x2591fd3]

  • 说句实话,我以前一直以为表结构变更是把变更的追加到数据字典上。看到这里我发现我以前想的不对。
  • 别人告诉我,他们是add partition。但是从这句看上去,他要先执行一次把现有的结构从cache中移除。那么我想应该是先移除,再增加这么一个过程。
  • 那么增加字段估计也是这样。

/usr/sbin/mysqld() [0x226f786] /usr/sbin/mysqld() [0xf4b9c1] /usr/sbin/mysqld(mysql_alter_table(THD*, char const*, char const*, HA_CREATE_INFO*, TABLE_LIST*, Alter_info*)+0x935e) [0xf628ce] /usr/sbin/mysqld(Sql_cmd_alter_table::execute(THD*)+0x4bd) [0x13340ed] /usr/sbin/mysqld(mysql_execute_command(THD*, bool)+0x9f0) [0xeb98d0] /usr/sbin/mysqld(mysql_parse(THD*, Parser_state*)+0x42b) [0xebe03b] /usr/sbin/mysqld(dispatch_command(THD*, COM_DATA const*, enum_server_command)+0x1ecc) [0xec03ac] /usr/sbin/mysqld(do_command(THD*)+0x19c) [0xec101c] /usr/sbin/mysqld() [0xfe69e0] /usr/sbin/mysqld() [0x272fc3e] /lib64/libpthread.so.0(+0x7ea5) [0x7f9efd1a3ea5] /lib64/libc.so.6(clone+0x6d) [0x7f9efb58996d]

Trying to get some variables. Some pointers may be invalid and cause the dump to abort.

  • Query (7f99ec124958): alter table 这里是表名 ADD PARTITION ( PARTITION tp202702 VALUES LESS THAN (to_days(‘2027-03-01 00:00:00’)))
  • 可以看出来确实是增加分区。

分析

  • 这种DDL本身没有问题,主要是get_ref_count() == 0这里判断有数据库对象在使用。我觉得这是问题点。如果执行DDL的时刻没有这个表相关的SQL在长时间占用的话也不会有问题。
  • 我记得多年前遇到数据库实例关闭的情况,当时主要是MySQL5.7,很多人说这是数据库bug(可能更多的来自于MySQL自己的日志输出,他本身就说这个可能是一个bug,不管什么奔溃,都这么说。这就其他人上来就觉得是一个bug)。当时很多人说要么升级吧。
  • 我说,还是先解决SQL吧。最后结果是SQL改好的数据库,后来没再出过问题。而有些数据库升级以后,该出问题的还是出过。
  • 所以到了今天,我依然觉得这种要从根本上解决的话,还是让SQL高效一些。不要过多消耗,因为长时间的执行过程,元数据必然也是锁定的。
  • 假设使用了最新版本,我不相信一个表上大量同时都是全表查询或者全表锁定的时候,DDL会不出问题。
  • 就这个问题,我又去问了一下找我的人。他说执行卡住了,然后关了工具。可能涉及到被kill。这个当时他没说。如果是这个,可能就触发MySQL的bug。
  • 所以最好的就是没有对表读写的情况下执行增加分区,如果不幸遇到了。那么就kill掉其他SQL,确保DDL的执行。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 接到别人求助:有个数据库重启了看看是什么原因?
  • 具体出错日志
  • 分析
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档