mysql 更新故障,启动不起来

594 阅读2分钟

mysql 更新故障,启动不起来

问题说明

使用docker启动的mysql服务,使用的mysql:latest镜像,对应的是8.0.31版本,数据是挂载在本地的磁盘上。最近其他项目,更新了mysql镜像,当前mysql:latest 对应是8.4.0版本。也就是本地更新了镜像,但是镜像的名称跟我之前使用的是一样的。

导致了我启动mysql的时候,启动不起来。查看docker 启动容器的日志,显示mysql更新失败了。 当我把docker-compose中mysql的镜像,还原到8.0.31版本的时候,还是启动不起来,日志显示mysql无法降级。

尝试的解决方法

  1. 重新启动一个mysql,镜像8.0.31版本,然后把坏了的mysql中的所有数据库文件夹拷贝过去。 结果是启动之后,新的mysql看不到这些数据库

  2. 尝试把其他文件也拷贝过去。也启动不了。发现mysql.ibd 这个文件被新版的mysql8.4.0更新了,这个文件中包含了各个数据库的元数据。

最后就是无解。8.4.0更新了mysql.ibd,在8.0.31中无法使用。而且mysql.ibd 中还包含了数据库元数据,又必须要这个文件。这个文件还是二进制的,无法修改。

解决方法

解决方法参考

各个数据库,各自存在一个文件夹中,数据库中的一个表对应一个 .ibd文件。如果能直接从 .ibd中把数据导出来或者转化一下,就能恢复数据库。

image.png

解决步骤。

  1. mysql 8.0.31 镜像新启一个容器。
  2. 创建同名的数据库
  3. 创建同名的表,表的结构要和原来旧的表一致。
  4. mysql命令删除.ibd 表空间
  5. 拷贝旧的.ibd 文件到现在新的数据库中同样位置
  6. 绑定新数据库中的表和旧数据

如果不知道旧的表结构如何解决?(这个步骤我没操作,因为我有表结构的备份)

mysql自带的一个工具ibd2sdi可以从 .ibd中提取表结构

#在.ibd所在的文件夹下执行
ibd2sdi --dump-file name.txt name.ibd

查看解析后的txt文件,可以看到8.0版本的mysql把表结构、索引全部都放到了表数据文件ibd文件中了(然后你就可以在数据库中创建结构相同的表了)

如何删除新的.ibd和绑定旧的.ibd文件,即表空间?

  1. docker 启动容器
  2. 进入docker内部,mysql命令行登陆
  3. 选择目标数据库
  4. 删除表空间
alter table table_name DISCARD TABLESPACE
  1. 拷贝旧的.ibd文件到对应文件夹
  2. 重新绑定(导入)表空间
alter table table_name IMPORT TABLESPACE

如果表结构不一致,导入会报错的。