• 售前

  • 售后

热门帖子
入门百科

MySQL 利用frm文件和ibd文件恢复表数据

[复制链接]
珍惜637 显示全部楼层 发表于 2021-10-27 20:21:59 |阅读模式 打印 上一主题 下一主题
目录


  • frm文件和ibd文件简介
  • frm文件规复表结构
  • ibd文件规复表数据
  • 简朴总结一下

frm文件和ibd文件简介

   在MySQL中,如果我们利用了默认的存储引擎innodb创建一张表,那么在文件夹下面就会出现表名.frm和表名.ibd两个文件,如果我们利用的是Myisam存储引擎,那么就会出现三个文件,这里我们给出例子:
  1. [root@ /data/yeyz]#ll
  2. total 580
  3. -rw-rw---- 1 mysql mysql 8586 Apr 3 17:44 a.frm
  4. -rw-rw---- 1 mysql mysql  0 Apr 3 17:44 a.MYD
  5. -rw-rw---- 1 mysql mysql 1024 Apr 3 17:44 a.MYI
  6. -rw-rw---- 1 mysql mysql 8586 Apr 3 17:44 b.frm
  7. -rw-rw---- 1 mysql mysql 98304 Apr 3 17:45 b.ibd
  8. -rw-rw---- 1 mysql mysql 61 Nov 23 09:54 db.opt
  9. -rw-rw---- 1 mysql mysql 8556 Apr 29 21:37 tbl_test_2.frm
  10. -rw-rw---- 1 mysql mysql 98304 Apr 29 21:37 tbl_test_2.ibd
  11. -rw-rw---- 1 mysql mysql 8556 Apr 29 21:33 tbl_test.frm
  12. -rw-rw---- 1 mysql mysql 98304 Apr 29 21:33 tbl_test.ibd
  13. -rw-rw---- 1 mysql mysql 8614 Apr 29 21:40 test.frm
  14. -rw-rw---- 1 mysql mysql 98304 Apr 29 21:43 test.ibd
  15. -rw-rw---- 1 mysql mysql 8666 Apr 2 15:13 unstandard_ins.frm
  16. -rw-rw---- 1 mysql mysql 98304 Apr 3 11:46 unstandard_ins.ibd
  17. -rw-rw---- 1 mysql mysql 8586 Apr 3 17:44 yeyz.frm
  18. -rw-rw---- 1 mysql mysql 28 Apr 3 17:44 yeyz.MYD
  19. -rw-rw---- 1 mysql mysql 2048 Apr 3 17:44 yeyz.MYI
复制代码
此中ibd文件是innodb的表数据文件,而frm文件是innodb的表结构文件,mysiam存储引擎的表中,frm是表结构,MYI文件是索引文件,而MYD文件是数据文件,从这里也可以看出,innodb存储引擎的索引和数据是在一起的,而Myisam存储引擎索引和数据是分开的。
必要注意的是,这个frm文件和ibd文件都是不能直接打开的。
思量如许一种需求,数据库必要快速规复一个表中的数据,而这个表地点的库的数据量非常大,规复起来可能泯灭的时间也比较长,那么全库规复肯定不是最佳的选择。那这种情况下怎么办呢?我们可以利用frm文件盒ibd文件来对数据举行规复。下面我们分析分析这个过程。

frm文件规复表结构

    固然,表结构必要利用frm文件来规复。我们第一反应想到的是,可以把这两个文件直接拷贝到一个新的数据库实例中,然后直接启动实例,如允许以么?固然是不可的。侄儿要是能行,估计DBA都可以下岗了。哈哈,废话不多说,来看操纵过程。
    起首,我们创建一个新的实例专门用来规复数据,如果你利用线上的某一台机器来实行规复,那你必须承担数据库重启的风险以及DML壅闭的风险,所以最好的方法照旧利用一台专门的实例来举行规复。那么我们如何从frm文件中拿到我们想要的表结构呢?
   我拿线上的一个纪录慢日记的表举个例子,为了写着方便,表名称我写成了"aaa",这个表的结构是如许的:
  1. mysql--root@localhost:test_recover 12:08:43>>show create table aaa\G
  2. *************************** 1. row ***************************
  3.   Table: aaa
  4. Create Table: CREATE TABLE `aaa` (
  5. `maintain_id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增列',
  6. `slowquery_filename` varchar(50) DEFAULT NULL COMMENT '慢日志文件名',
  7. `slowquery_path` varchar(150) DEFAULT NULL COMMENT '慢日志全路径',
  8. `slowquery_process` tinyint(20) unsigned NOT NULL DEFAULT '0' COMMENT '慢日志是否被解析',
  9. `slowquery_uploadtime` datetime DEFAULT CURRENT_TIMESTAMP,
  10. `slowquery_analyzetime` date DEFAULT NULL COMMENT '慢日志解析时间',
  11. `slowquery_starttime` date DEFAULT NULL,
  12. `slowquery_endtime` date DEFAULT NULL,
  13. `instance_ip` varchar(15) DEFAULT NULL COMMENT '慢日志IP地址',
  14. `instance_port` int(11) DEFAULT NULL COMMENT '慢日志端口号地址',
  15. PRIMARY KEY (`maintain_id`)
  16. ) ENGINE=InnoDB DEFAULT CHARSET=utf8
  17. 1 row in set, 1 warning (0.01 sec)
复制代码
  要从frm文件中得到如许的一个表,我们要做的步调如下:
1、在实例上创建一个同名的表aaa,由于我们不知道这个表的结构,我们可以给它设定只有一个字段id,也就是
create table aaa (id int);
我们知道,这个时间会在对应的data目录下天生新的aaa.frm和aaa.ibd文件,然后我们利用我们备份的aaa.frm来替代之前的aaa.frm,然后重启数据库。
是的,你没有看错,我们利用备份的表结构文件来替代它天生的表结构文件。
2.看看重启之后错误日记输出的结果吧,如下:
  1. 2019-03-22T03:17:28.652390Z 16
  2. [Warning] InnoDB: Table test_recover/store_goods_price contains 1 user
  3. defined columns in InnoDB, but 12 columns in MySQL. Please check
  4. INFORMATION_SCHEMA.INNODB_SYS_COLUMNS and http://dev.mysql.com/doc/refman/5.7/en/innodb-troubleshooting.html for how to resolve the issue.
  5. 2019-04-02T07:56:31.558461Z 41
  6. [Warning] InnoDB: Table test_recover/dv_control contains 1 user defined
  7. columns in InnoDB, but 14 columns in MySQL. Please check
  8. INFORMATION_SCHEMA.INNODB_SYS_COLUMNS and http://dev.mysql.com/doc/refman/5.7/en/innodb-troubleshooting.html for how to resolve the issue.
  9. 2019-05-23T03:14:10.161122Z 92
  10. [Warning] InnoDB: Table test_recover/aaa contains 1
  11. user defined columns in InnoDB, but 10 columns in MySQL. Please check
  12. INFORMATION_SCHEMA.INNODB_SYS_COLUMNS and http://dev.mysql.com/doc/refman/5.7/en/innodb-troubleshooting.html for how to resolve the issue.
复制代码
   可以看到,10-12行的错误日记里面提示我们这个表aaa只包含1个字段,但是frm中包含10个字段,字段的数目不符。
    这和我们预料的结果符合,由于我们在创建表aaa的时间,只给了他1个字段id,而我们要规复的aaa表有10个字段,肯定是无法从frm中读取的。此时你可能很容易就能想到,如果我们把这个aaa表的字段调成10个,那么终极的结果是什么呢?
3.将aaa表的字段数目升级成10个,然后重新拷贝frm文件,修改设置文件中的参数innodb_force_recovery=6,我们看看终极的结果:
  1. mysql--root:(none) 12:04:20>>use test_recover;
  2. Database changed
  3. mysql--root:test_recover 12:04:25>>create table aaa (id1 int,id2 int,id3 int,id4 int,id5 int,id6 int,id7 int,id8 int,id9 int,id10 int);
  4. Query OK, 0 rows affected (0.03 sec)
  5. mysql--root@localhost:test_recover 12:05:08>>show create table aaa\G
  6. *************************** 1. row ***************************
  7.   Table: aaa
  8. Create Table: CREATE TABLE `aaa` (
  9. `id1` int(11) DEFAULT NULL,
  10. `id2` int(11) DEFAULT NULL,
  11. `id3` int(11) DEFAULT NULL,
  12. `id4` int(11) DEFAULT NULL,
  13. `id5` int(11) DEFAULT NULL,
  14. `id6` int(11) DEFAULT NULL,
  15. `id7` int(11) DEFAULT NULL,
  16. `id8` int(11) DEFAULT NULL,
  17. `id9` int(11) DEFAULT NULL,
  18. `id10` int(11) DEFAULT NULL
  19. ) ENGINE=InnoDB DEFAULT CHARSET=utf8
  20. 1 row in set (0.00 sec)
复制代码
  然后我们重启实例,再次查看表aaa,可以看到结果如下:
  1. mysql--root:test_recover 12:08:43>>show create table aaa\G
  2. *************************** 1. row ***************************
  3.   Table: aaa
  4. Create Table: CREATE TABLE `aaa` (
  5. `maintain_id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增列',
  6. `slowquery_filename` varchar(50) DEFAULT NULL COMMENT '慢日志文件名',
  7. `slowquery_path` varchar(150) DEFAULT NULL COMMENT '慢日志全路径',
  8. `slowquery_process` tinyint(20) unsigned NOT NULL DEFAULT '0' COMMENT '慢日志是否被解析',
  9. `slowquery_uploadtime` datetime DEFAULT CURRENT_TIMESTAMP,
  10. `slowquery_analyzetime` date DEFAULT NULL COMMENT '慢日志解析时间',
  11. `slowquery_starttime` date DEFAULT NULL,
  12. `slowquery_endtime` date DEFAULT NULL,
  13. `instance_ip` varchar(15) DEFAULT NULL COMMENT '慢日志IP地址',
  14. `instance_port` int(11) DEFAULT NULL COMMENT '慢日志端口号地址',
  15. PRIMARY KEY (`maintain_id`)
  16. ) ENGINE=InnoDB DEFAULT CHARSET=utf8
  17. 1 row in set, 1 warning (0.01 sec)
复制代码
   可以看到,我们想要的表结构已经从frm文件中规复出来了,必要注意的是,这个过程中我们并没有利用ibd文件。
总结一下利用frm文件规复表结构的步调:
1、起首创建一个同名的表,然后启动实例
2、利用备份的frm文件替代天生的frm文件,重启实例
3、查看错误日记,从错误日记中获取到备份的frm文件中的字段数目m
4、重新创建同名表,包管字段数目为m,与备份表保持一致,然后重新拷贝备份的frm文件到对应目录
5、修改实例的设置文件中的参数innodb_force_recovery=6,然后重启数据库,就可以看到对应的表结构创建语句,我们把它生存下来,下一步规复数据的时间要用。这一步相称紧张
6、将参数innodb_force_recovery=6注释掉,重新利用默认的值,然后重启数据库,准备规复表数据。
    至此,表结构规复完毕。
    表明一下innodb_force_recovery参数,这个参数的最大值是6,在该等级下,仅支持一部分查询功能,DML都不支持,从名称就可以看出来,这是在一些强行规复的场景下才会利用的参数,一样平常情况下这个参数可以不要,利用默认值就行。有兴趣更深相识的同学可以参考官方文档。

ibd文件规复表数据

   上一步实行完成之后,我们已经获取了对应的表结构,如今我们看看如何规复表数据。
   规复表数据的方法比较简朴,大要步调如下:
1、利用我们上一步中获取的建表语句,重新创建一张表,然后实行:
flush  table aaa for export;
这个语法是将表里面的数据落盘,并获取该表的锁,为后面规复做好准备。
2、然后我们利用如下语句:
alter table aaa discard tablespace;
这个语句会删除当前的ibd文件。
3、然后我们利用我们之前备份的ibd文件,将其拷贝到对应的实例目录下面
4、末了在将ibd文件重新加载进来,利用如下语句:
alter table aaa import tablespace;
重启数据库,如许,我们的数据就规复成功了。

简朴总结一下

   整个规复的流程算是先容完了,此中比较奥妙的地方就是从frm文件中获取表结构信息,我们利用了两次拼集表创建语句的方法,终极得到了待规复的表的表结构,然后利用alter table discard tablespace和alter table import tablespace的方法来规复表中的数据。整个过程看着比较复杂,实在完全可以按照步调抽象出来一个脚本,如许在下次规复的时间,只必要输入要规复的表的名称,就可以快速的规复表结构和数据,不失为一种应急的数据规复预案。
以上就是MySQL 利用frm文件和ibd文件规复表数据的具体内容,更多关于MySQL 规复表数据的资料请关注草根技术分享其它相干文章!

帖子地址: 

回复

使用道具 举报

分享
推广
火星云矿 | 预约S19Pro,享500抵1000!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

草根技术分享(草根吧)是全球知名中文IT技术交流平台,创建于2021年,包含原创博客、精品问答、职业培训、技术社区、资源下载等产品服务,提供原创、优质、完整内容的专业IT技术开发社区。
  • 官方手机版

  • 微信公众号

  • 商务合作