看到percona发了篇Do Not Upgrade to Any Version of MySQL After 8.0.37. 说是mysql新版本有BUG.
当数据库存在大量的表的时候, 重启就会crash.
本次使用Mysql 8.0.38 社区版做测试. 可使用如下脚本快速创建10001张表
import pymysql
conn = pymysql.connect(
host='127.0.0.1',
port=3376,
user='root',
password='123456',
)
for i in range(10001):
cursor = conn.cursor()
#cursor.execute(f'drop table db1.t20240712_{i}')
cursor.execute(f'create table db1.t20240712_{i}(id int, name varchar(200))')
data = cursor.fetchall()
conn.commit()
然后重启mysqld进程. 我们就能在日志中发现如下crash信息
2024-07-12T02:36:45.561391Z 1 [System] [MY-013577] [InnoDB] InnoDB initialization has ended.
2024-07-12T02:36:45Z UTC - mysqld got signal 11 ;
Most likely, you have hit a bug, but this error can also be caused by malfunctioning hardware.
BuildID[sha1]=96a3ee772d1d213bc36262ae5f5c23c7b9f61b30
Thread pointer: 0x0
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 = 0 thread_stack 0x100000
/soft/mysql_3376/mysqlbase/mysql/bin/mysqld(my_print_stacktrace(unsigned char const*, unsigned long)+0x3d) [0x212497d]
/soft/mysql_3376/mysqlbase/mysql/bin/mysqld(print_fatal_signal(int)+0x37f) [0xfe3fff]
/soft/mysql_3376/mysqlbase/mysql/bin/mysqld(handle_fatal_signal+0xa5) [0xfe40b5]
/lib64/libpthread.so.0(+0xf630) [0x7fc6e4cee630]
/soft/mysql_3376/mysqlbase/mysql/bin/mysqld(Validate_files::check(__gnu_cxx::__normal_iterator<dd::Tablespace const* const*, std::vector<dd::Tablespace const*, std::allocator<dd::Tablespace const*> > > const&, __gnu_cxx::__normal_iterator<dd::Tablespace const* const*, std::vector<dd::Tablespace const*, std::allocator<dd::Tablespace const*> > > const&, unsigned long)+0x8ae) [0x2170c8e]
/soft/mysql_3376/mysqlbase/mysql/bin/mysqld(std::thread::_State_impl<std::thread::_Invoker<std::tuple<Detached_thread, std::function<void (__gnu_cxx::__normal_iterator<dd::Tablespace const* const*, std::vector<dd::Tablespace const*, std::allocator<dd::Tablespace const*> > > const&, __gnu_cxx::__normal_iterator<dd::Tablespace const* const*, std::vector<dd::Tablespace const*, std::allocator<dd::Tablespace const*> > > const&, unsigned long)>, __gnu_cxx::__normal_iterator<dd::Tablespace const* const*, std::vec/soft/mysql_3376/mysqlbase/mysql/bin/mysqld() [0x2ae5974]
/lib64/libpthread.so.0(+0x7ea5) [0x7fc6e4ce6ea5]
/lib64/libc.so.6(clone+0x6d) [0x7fc6e30fb96d]
The manual page at http://dev.mysql.com/doc/mysql/en/crashing.html contains
information that should help you find out what is causing the crash.
看起来是做文件校验(Validate_files)的时候crash的. 具体原因得后面有空再看相关代码了. 建议先不要使用mysql新版.
刚才在群里看到有群友反馈有客户反馈该问题了. 那么遇到这种情况了该怎么办呢?
我们知道使用高版本的mysqld启动之后, 是没法再使用低版本的mysqld启动的. 难道就只能等mysql官方发布下一个版本了吗? 或者从备份回退回去. 这都不太现实. 所以这里给出2个简单的方法.(都不太推荐...)
ibd2sql可以从ibd文件中提取出数据, 所以只要写个脚本批量解析出来, 然后重新导入正常的数据库即可.
下载地址: https://github.com/ddcw/ibd2sql
优点: 简单, 还万能...
缺点: 使用量太少, 可能存在未知BUG
根据堆栈信息我们可以知道是Validate_files::check
的时候报错的, 那么理论上我们只要注释掉该函数即可.
我们可以使用addr2line
找到堆栈信息对应的函数位置.
注: 官方的二进制文件可能找不到(无debug信息), 我这里就单独编译了一个.(这是已经修复过的, 所以和实际环境存在差异)
addr2line -e /root/mysql_source/mysql-8.0.38/bldx86/runtime_output_directory/mysqld 0x21708be
然后注释掉该调用即可, 我这里就直接让函数返回空了.(根除这个BUG. 不是修复). 更深层的原因我们就先不看了(有空了再说)
编辑 storage/innobase/handler/ha_innodb.cc
在第3431行
添加return ;
即可
然后重新编译并启动数据库验证 发现启动成功了
登录数据库查看数据也是正常的
然后记得把数据导出来,回退到低版本去.
优点: 官方的mysql启动的
缺点: 修改过部分源码
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。