最新一期鬼故事来了。
某位朋友的网站之前运行的是 FreeBSD 12,后来一路升级,今天他老人家发消息说从 FreeBSD 14.0 升级到 FreeBSD 14.1 之后 MySQL 无法启动了,具体消息是:
我感觉这属于跨版本 ABI 变动没有抓到的重大发布事故,然而我本地的 /lib/libc++.so.1 有这个符号,并且全新安装的一份干净的 FreeBSD 14.1 上无法重现他的问题,于是要了一个 shell 登录上去看。
接下来惊喜地发现他的 mysqld 使用的是 /usr/local/lib/libc++.so.1,该文件是 libc++-208080 提供的。此包删除于2017年 https://svnweb.freebsd.org/ports?view=revision&revision=434738
删掉这个包之后 mysqld 可以动了,但又有了新问题: InnoDB 的 redo log 格式版本是0,新的 MySQL 版本不支持。
于是问题变成了需要找一份旧的 MySQL 来先启动起来,做一个 dump,升级 MySQL,重建数据库,然后从 dump 恢复。但是 MySQL 5.7 并不支持 FreeBSD 14,而且去年年底已经被砍掉了,于是搞了一个 FreeBSD 13.3 的 poudriere builder,把 ports tree 恢复到 2023Q4 来build了一份包,传到该机器上,替换掉 MySQL 8.4,这下 MySQL 终于可以启动了。
mysqldump做完之后安装新版 MySQL,删掉整个 mysql 目录,初始化 MySQL 数据库,将 *.cnf 复制回新的 mysql 目录中,然后 mysql -u root < dump,结果:
所以为什么 MySQL dump的时候连这类 stats 表也跟着一起?因为实在不想再重装一遍 MySQL 5.7,手工编辑了一下dump删掉了innodb的这些stats表的部分,这下再导入时:
这题我会,我想,于是在 my.cnf 中添加了 max_allowed_packet=1024M,这下终于导入成功了。导入之后发现:
然后发现了 https://dev.mysql.com/doc/refman/8.4/en/native-pluggable-authentication.html 。
嗯。
暂时重新启用了该插件。这下这哥们的网站总算是活过来了。
我觉得这事也不全怪 Oracle,毕竟 MySQL 5.7 在 2019 年就已经停止支持了(我就差跟这哥们说 「#你的备份呢?」 了),不过他们的数据结构支持砍的太激进了点儿。幸亏我手里还有一份之前的源代码可以重新搞一份包,不然这哥们的数据估计就交代了。
顺手看了一眼我自己的 MySQL 实例,发现我的许多 Web 服务也还在用 mysql_native_password。想了想,去票务系统里给自己开了个票,当年(2005)我做网站的时候就已经实现了用户首次登录时,如果密码验证通过的话立即把密码格式换成新的,没想到这都 2024 年了 MySQL 的做法居然是直接把问题丢给DBA……
所以今天的教训是:
1. 我个人的老生常谈:做备份,做备份,做备份。软件和数据都要做备份。
2. 平时没事多做升级,把软件弄到最新版,趁着系统维护的时间把问题暴露出来。
3. 珍爱生命,远离 Oracle 的任何产品。那位说了, PostgreSQL 也要求 dump / restore 不是吗?但人家至少知道每个大版本起一个新的目录。
#今天份草台
某位朋友的网站之前运行的是 FreeBSD 12,后来一路升级,今天他老人家发消息说从 FreeBSD 14.0 升级到 FreeBSD 14.1 之后 MySQL 无法启动了,具体消息是:
ld-elf.so.1: /usr/local/libexec/mysqld: Undefined symbol "_ZTVSt19bad_optional_access"
我感觉这属于跨版本 ABI 变动没有抓到的重大发布事故,然而我本地的 /lib/libc++.so.1 有这个符号,并且全新安装的一份干净的 FreeBSD 14.1 上无法重现他的问题,于是要了一个 shell 登录上去看。
接下来惊喜地发现他的 mysqld 使用的是 /usr/local/lib/libc++.so.1,该文件是 libc++-208080 提供的。此包删除于2017年 https://svnweb.freebsd.org/ports?view=revision&revision=434738
删掉这个包之后 mysqld 可以动了,但又有了新问题: InnoDB 的 redo log 格式版本是0,新的 MySQL 版本不支持。
于是问题变成了需要找一份旧的 MySQL 来先启动起来,做一个 dump,升级 MySQL,重建数据库,然后从 dump 恢复。但是 MySQL 5.7 并不支持 FreeBSD 14,而且去年年底已经被砍掉了,于是搞了一个 FreeBSD 13.3 的 poudriere builder,把 ports tree 恢复到 2023Q4 来build了一份包,传到该机器上,替换掉 MySQL 8.4,这下 MySQL 终于可以启动了。
mysqldump做完之后安装新版 MySQL,删掉整个 mysql 目录,初始化 MySQL 数据库,将 *.cnf 复制回新的 mysql 目录中,然后 mysql -u root < dump,结果:
Access to system table 'mysql.innodb_index_stats' is rejected.
所以为什么 MySQL dump的时候连这类 stats 表也跟着一起?因为实在不想再重装一遍 MySQL 5.7,手工编辑了一下dump删掉了innodb的这些stats表的部分,这下再导入时:
Got a packet bigger than 'max_allowed_packet' bytes
这题我会,我想,于是在 my.cnf 中添加了 max_allowed_packet=1024M,这下终于导入成功了。导入之后发现:
mysql: ERROR 1524 (HY000): Plugin 'mysql-native-password' is not loaded
然后发现了 https://dev.mysql.com/doc/refman/8.4/en/native-pluggable-authentication.html 。
嗯。
暂时重新启用了该插件。这下这哥们的网站总算是活过来了。
我觉得这事也不全怪 Oracle,毕竟 MySQL 5.7 在 2019 年就已经停止支持了(我就差跟这哥们说 「#你的备份呢?」 了),不过他们的数据结构支持砍的太激进了点儿。幸亏我手里还有一份之前的源代码可以重新搞一份包,不然这哥们的数据估计就交代了。
顺手看了一眼我自己的 MySQL 实例,发现我的许多 Web 服务也还在用 mysql_native_password。想了想,去票务系统里给自己开了个票,当年(2005)我做网站的时候就已经实现了用户首次登录时,如果密码验证通过的话立即把密码格式换成新的,没想到这都 2024 年了 MySQL 的做法居然是直接把问题丢给DBA……
所以今天的教训是:
1. 我个人的老生常谈:做备份,做备份,做备份。软件和数据都要做备份。
2. 平时没事多做升级,把软件弄到最新版,趁着系统维护的时间把问题暴露出来。
3. 珍爱生命,远离 Oracle 的任何产品。那位说了, PostgreSQL 也要求 dump / restore 不是吗?但人家至少知道每个大版本起一个新的目录。
#今天份草台
👍13❤1