mysql数据库frm文件丢失或ibd文件丢失

mysql数据库frm文件丢失或ibd文件丢失

一:模拟frm文件丢失:
这里以innodb为例
开启独立表空间 innodb_file_per_table;

create database test;
use test;
create table a(id int,num int); 
insert into  a values(1,11),(2,12);

mysql> create table a(id int,num int);
Query OK, 0 rows affected (0.01 sec)
mysql> insert into a values(1,11),(2,12);
Query OK, 2 rows affected (0.00 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql> select * from a;
+——+——+
| id | num |
+——+——+
| 1 | 11 |
| 2 | 12 |
+——+——+
2 rows in set (0.00 sec)

到物理机上直接删除a表对应的frm文件
[root@m89a01407.cloud.b03.am1319 /home/mysql/data3025/dbs3025/scott]
#ls
a.frm a.ibd db.opt
[root@m89a01407.cloud.b03.am1319 /home/mysql/data3025/dbs3025/scott]
#mv a.frm a.frm_bak
[root@m89a01407.cloud.b03.am1319 /home/mysql/data3025/dbs3025/scott]

删除完成之后:

mysql> use scott
Database changed
mysql> show tables;
Empty set (0.00 sec)
mysql> select * from a;
+——+——+
| id | num |
+——+——+
| 1 | 11 |
| 2 | 12 |
+——+——+
2 rows in set (0.00 sec)

mysql> desc a;
+——-+———+——+—–+———+——-+
| Field | Type | Null | Key | Default | Extra |
+——-+———+——+—–+———+——-+
| id | int(11) | YES | | NULL | |
| num | int(11) | YES | | NULL | |
+——-+———+——+—–+———+——-+
2 rows in set (0.00 sec)
神奇的现象来了:在没有执行drop table的时候,还是可以查询表,查看表结构的,执行后,就查不到了。
mysql> drop table a;
ERROR 1051 (42S02): Unknown table ‘scott.a’
mysql> desc a;
ERROR 1146 (42S02): Table ‘scott.a’ doesn’t exist
mysql> select * from a;
ERROR 1146 (42S02): Table ‘scott.a’ doesn’t exist

无论是对于数据表的增删查改,还是数据结构的增删查改。统统失效,连 information_schema.columns 都查不到(是因为执行了drop table,虽然报错了,但是把数据字典系统表里的相关信息还是删除了)。

如何彻底删除这个表?
随便找个表,这里新建另外一张表
mysql> create table b(inum int);
Query OK, 0 rows affected (0.01 sec)
mysql> insert into b values(2);
Query OK, 1 row affected (0.00 sec)
mysql> insert into b values(12);
Query OK, 1 row affected (0.00 sec)
mysql> commit;
Query OK, 0 rows affected (0.00 sec)

然后在物理机上进行操作:将新建的frm文件重命名为a.frm
[root@m89a01407.cloud.b03.am1319 /home/mysql/data3025/dbs3025/scott]
#ls
a.frm_bak a.ibd b.frm b.ibd db.opt

[root@m89a01407.cloud.b03.am1319 /home/mysql/data3025/dbs3025/scott]
#cp b.frm a.frm

[root@m89a01407.cloud.b03.am1319 /home/mysql/data3025/dbs3025/scott]
#ll
total 264
-rw-r—– 1 root root 8657 Nov 3 09:20 a.frm
-rw-r—– 1 mysql mysql 8681 Nov 3 09:09 a.frm_bak
-rw-r—– 1 mysql mysql 114688 Nov 3 09:09 a.ibd
-rw-r—– 1 mysql mysql 8657 Nov 3 09:18 b.frm
-rw-r—– 1 mysql mysql 114688 Nov 3 09:19 b.ibd
-rw-r—– 1 mysql mysql 67 Nov 3 08:26 db.opt

[root@m89a01407.cloud.b03.am1319 /home/mysql/data3025/dbs3025/scott]
#chown -R mysql:mysql a.frm

mysql> drop table a;
Query OK, 0 rows affected (0.00 sec)

mysql> commit;
Query OK, 0 rows affected (0.00 sec)
a.frm 加上之后,删除表后 ,这个名称就可以重建了。
[root@m89a01407.cloud.b03.am1319 /home/mysql/data3025/dbs3025/scott]
#ll
total 140
-rw-r—– 1 mysql mysql 8681 Nov 3 09:09 a.frm_bak
-rw-r—– 1 mysql mysql 8657 Nov 3 09:18 b.frm
-rw-r—– 1 mysql mysql 114688 Nov 3 09:19 b.ibd
-rw-r—– 1 mysql mysql 67 Nov 3 08:26 db.opt

如何恢复这个表?
新建与原表同样的表结构,然后将元数据文件复制为原表名同样的文件。即可恢复。
测试如下:
create table test(id int,num int);
insert into test values(1,11),(2,12);

[root@m89a01407.cloud.b03.am1319 /home/mysql/data3025/dbs3025/scott]
#mv test.frm test.bak

mysql> show create table test;
+——-+————————————————————————————————————————-+
| Table | Create Table |
+——-+————————————————————————————————————————-+
| test | CREATE TABLE test (
id int(11) DEFAULT NULL,
num int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 |
+——-+————————————————————————————————————————-+
1 row in set (0.00 sec)
当业务正常运行的时候,此时表查询将无影响。但是重启数据库后则表有问题:

mysql> show create table test;
ERROR 1146 (42S02): Table ‘scott.test’ doesn’t exist
mysql> show create table test;
ERROR 1146 (42S02): Table ‘scott.test’ doesn’t exist
mysql> select * from test;
ERROR 1146 (42S02): Table ‘scott.test’ doesn’t exist
mysql>
新建与原表同样的表结构,然后将元数据文件复制为原表名同样的文件。即可恢复。
mysql> create table test1 (
-> id int(11) DEFAULT NULL,
-> num int(11) DEFAULT NULL
-> ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
Query OK, 0 rows affected (0.05 sec)

mysql> exit
Bye

[root@m89a01407.cloud.b03.am1319 /home/mysql/data3025/dbs3025/scott]
#ls
a.frm_bak b.frm b.ibd db.opt test1.frm test1.ibd test.bak test.ibd

[root@m89a01407.cloud.b03.am1319 /home/mysql/data3025/dbs3025/scott]
#cp test1.frm test.frm

[root@m89a01407.cloud.b03.am1319 /home/mysql/data3025/dbs3025/scott]
#chown -R mysql:mysql test.frm

[root@m89a01407.cloud.b03.am1319 /home/mysql/data3025/dbs3025/scott]
XXXXXXXXXXXXXXXXXXXXXXxxxxxxxxxxxxxxxxxxxxxxx
Warning: Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 156
Server version: 5.7.28-log Source distribution

Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type ‘help;’ or ‘\h’ for help. Type ‘\c’ to clear the current input statement.

mysql> show create table test;
+——-+————————————————————————————————————————-+
| Table | Create Table |
+——-+————————————————————————————————————————-+
| test | CREATE TABLE test (
id int(11) DEFAULT NULL,
num int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 |
+——-+————————————————————————————————————————-+
1 row in set (0.00 sec)

mysql> desc test;
+——-+———+——+—–+———+——-+
| Field | Type | Null | Key | Default | Extra |
+——-+———+——+—–+———+——-+
| id | int(11) | YES | | NULL | |
| num | int(11) | YES | | NULL | |
+——-+———+——+—–+———+——-+
2 rows in set (0.01 sec)

mysql>

恢复完毕

二:ibd文件丢失
如果表数据不重要,可删除的话,可将frm共同删除。然后数据库中执行drop,虽然报错但是表名可复用。
#mv test1.ibd test1.bak

[root@m89a01407.cloud.b03.am1319 /home/mysql/data3025/dbs3025/scott]
#mysql -uaurora -p’Y1[fF-%OC0z7N[n’ –socket=/home/mysql/data3025/tmp/mysql.sock -A scott
Warning: Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 539
Server version: 5.7.28-log Source distribution

Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type ‘help;’ or ‘\h’ for help. Type ‘\c’ to clear the current input statement.

mysql> select count() from test1;
+———-+
| count(
) |
+———-+
| 0 |
+———-+
1 row in set (0.00 sec)
此时删除表报错,删除之后查询也报错:
mysql> drop table test1;
ERROR 1051 (42S02): Unknown table ‘scott.test1’
mysql> select * from test1;
ERROR 1146 (42S02): Table ‘scott.test1’ doesn’t exist
mysql> show create table test1;
ERROR 1146 (42S02): Table ‘scott.test1’ doesn’t exist
此时表名也不能使用:
mysql> create table test1 (a int);
ERROR 1146 (42S02): Table ‘scott.test1’ doesn’t exist

root@m89a01407.cloud.b03.am1319 /home/mysql/data3025/dbs3025/scott]
#mv test1.frm test1.frmbak

mysql> drop table test1;
ERROR 1051 (42S02): Unknown table ‘scott.test1’
mysql> create table test1 (a int);
Query OK, 0 rows affected (0.01 sec)

思考:没建表的情况下,可以直接用新建的frm和要恢复的ibd使用表空间导入嘛?
  不可以,会报错表不存在。而后,即使你新建表也会报错。

可否直接替换ibd?
    我建完一个同表结构新的空表之后,可不可以直接用我们需要恢复的ibd文件,替换这个ibd文件呢?

不可以;实际测试即使替换也会出现问题

当出现ibd文件丢失的情况,数据将丢失,暂时没有找到恢复办法