MySQL 通过ibd恢复数据

个人学习笔记,谢绝转载!!!

原文:https://www.cnblogs.com/wshenjin/p/14780723.html


故障背景:线上一台老数据库跑在单盘上,因坏道导致ibdata损坏。
恢复前提:表ibd文件正常,开启innodb_file_per_table。

安装mysqlfrm以读取表结构

[root@ ~]#  wget https://downloads.mysql.com/archives/get/p/30/file/mysql-utilities-1.6.5.tar.gz
[root@ ~]#  tar -xvzf mysql-utilities-1.6.5.tar.gz 
[root@ ~]#  cd mysql-utilities-1.6.5
[root@ ~]#  python ./setup.py build
[root@ ~]#  python ./setup.py install

导出故障实例表结构

[root@ ~]#  /usr/bin/mysqlfrm --diagnostic /data/database/mysql/testdb/user_info.frm

恢复数据

新起一个MySQL5.7新实例,在新实例上建相同的表,并卸载表空间

(root@localhost) > alter table testdb.user_info discard tablespace;

将故障库user_info表的ibd文件(testdb/user_info.ibd)拷贝到新实例对应的路径

挂在表空间

(root@localhost) > alter table testdb.user_info import tablespace;

如果报错Error Code: 1808. Schema mismatch (Table has ROW_TYPE_DYNAMIC row format, .ibd file has ROW_TYPE_COMPACT row format.)
则在建表语句后加上  ROW_FORMAT=COMPACT

至此,user_info表就恢复了。

另一种方法(mysql5.5):

新起一个MySQL5.5新实例,在新实例上建相同的表,关闭数据库。从新表的ibd文件(testdb/user_info.ibd)中获取新表的tablespace id :

[root@ ~]#  hexdump -C /data/database/mysql/testdb/user_info.ibd | head -3                                           
00000000  55 e6 77 a3 00 00 00 00  00 00 00 00 00 00 00 00  |U.w.............|
00000010  00 00 00 00 00 00 35 69  00 08 00 00 00 00 00 00  |......5i........|
00000020  00 00 00 00 00 e2 00 00  00 e2 00 00 00 00 00 00  |................|

从上面可以知道,新表的tablespace id是 00e2(16进制)。
这时用vim -b打开旧表的idb文件(testdb/user_info.ibd),vim打开后输入 :%!xxd 转换为16进制,大致如下:

0000000: 6372 4c23 0000 0000 0000 0000 0000 0000  crL#............
0000010: 0000 0000 0696 f666 0008 0000 0000 0000  .......f........
0000020: 0000 0000 00d6 0000 00d6 0000 0000 0000  ................
0000030: 0007 0000 0040 0000 0000 0000 0005 0000  .....@..........
0000040: 0000 ffff ffff 0000 ffff ffff 0000 0000  ................
0000050: 0001 0000 0000 009e 0000 0000 009e 0000  ................

可以看到旧表的tablespace id是 00d6(16进制)。
修改为00e2,再输入 :%!xxd -r 保存,最后wq退出vim。

将故障库user_info表的ibd文件(testdb/user_info.ibd)拷贝到新实例对应的路径。

最后MySQL的配置my.cnf中配置以下两个选项:

innodb_force_recovery=6
innodb_purge_threads=0

启动数据库,user_info表即恢复了。只要将user_info表重新导出导入到旧库即可。
如果不配置上面两个选项,数据库会认为user_info已被损坏。变更了新的tablespace id后的.ibd表文件,启动数据库后只能认出数据,但不能写入,这是因为原ibdata文件不仅保存了space id索引,还同时保存了一些其它的元数据。为了使元数据补全,所以采取导出、再导入的操作。

参考:

https://blog.csdn.net/u012887385/article/details/54406712
https://blog.csdn.net/weixin_31478029/article/details/113171741
https://www.cnblogs.com/gered/p/12524586.html
https://mp.weixin.qq.com/s/Iad4qT_vG9B3vBhvQ2p_2g

posted @   wshenJin  阅读(1010)  评论(0编辑  收藏  举报
编辑推荐:
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
阅读排行:
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· DeepSeek在M芯片Mac上本地化部署
· 葡萄城 AI 搜索升级:DeepSeek 加持,客户体验更智能
点击右上角即可分享
微信分享提示