mysql 更新故障,启动不起来
问题说明
使用docker启动的mysql服务,使用的mysql:latest镜像,对应的是8.0.31版本,数据是挂载在本地的磁盘上。最近其他项目,更新了mysql镜像,当前mysql:latest 对应是8.4.0版本。也就是本地更新了镜像,但是镜像的名称跟我之前使用的是一样的。
导致了我启动mysql的时候,启动不起来。查看docker 启动容器的日志,显示mysql更新失败了。 当我把docker-compose中mysql的镜像,还原到8.0.31版本的时候,还是启动不起来,日志显示mysql无法降级。
尝试的解决方法
-
重新启动一个mysql,镜像8.0.31版本,然后把坏了的mysql中的所有数据库文件夹拷贝过去。 结果是启动之后,新的mysql看不到这些数据库
-
尝试把其他文件也拷贝过去。也启动不了。发现mysql.ibd 这个文件被新版的mysql8.4.0更新了,这个文件中包含了各个数据库的元数据。
最后就是无解。8.4.0更新了mysql.ibd,在8.0.31中无法使用。而且mysql.ibd 中还包含了数据库元数据,又必须要这个文件。这个文件还是二进制的,无法修改。
解决方法
各个数据库,各自存在一个文件夹中,数据库中的一个表对应一个 .ibd文件。如果能直接从 .ibd中把数据导出来或者转化一下,就能恢复数据库。
解决步骤。
- mysql 8.0.31 镜像新启一个容器。
- 创建同名的数据库
- 创建同名的表,表的结构要和原来旧的表一致。
- mysql命令删除.ibd 表空间
- 拷贝旧的.ibd 文件到现在新的数据库中同样位置
- 绑定新数据库中的表和旧数据
如果不知道旧的表结构如何解决?(这个步骤我没操作,因为我有表结构的备份)
mysql自带的一个工具ibd2sdi可以从 .ibd中提取表结构
#在.ibd所在的文件夹下执行
ibd2sdi --dump-file name.txt name.ibd
查看解析后的txt文件,可以看到8.0版本的mysql把表结构、索引全部都放到了表数据文件ibd文件中了(然后你就可以在数据库中创建结构相同的表了)
如何删除新的.ibd和绑定旧的.ibd文件,即表空间?
- docker 启动容器
- 进入docker内部,mysql命令行登陆
- 选择目标数据库
- 删除表空间
alter table table_name DISCARD TABLESPACE
- 拷贝旧的.ibd文件到对应文件夹
- 重新绑定(导入)表空间
alter table table_name IMPORT TABLESPACE
如果表结构不一致,导入会报错的。