解决思路:利用独立表空间的方式将业务库的.ibd结尾的文件,导出,然后在一个新的数据库中,创建表结构一样的数据库,然后导入表空间。

这个方式相当于不修复原来的数据库(因为共享表空间坏了,那个比较难搞)但是这样的方式可以实现业务库可以恢复到一个新的数据库上,不影响使用。

这样做的一个难题就是,ibdata1共享表空间坏了,我们要怎么知道数据库下的表结构呢?

用到了mysqlfrm工具

可以得知业务库的表结构,那么就可以解决问题了。
恢复业务库,搞起。

下载

yum install https://mirrors.tuna.tsinghua.edu.cn/epel/7/x86_64/Packages/m/mysql-connector-python-1.1.6-1.el7.noarch.rpm
yum install https://mirrors.tuna.tsinghua.edu.cn/epel/7/x86_64/Packages/m/mysql-utilities-1.3.6-1.el7.noarch.rpm

第一步:得知原来数据库的表结构,以便我们在新的数据库中创建出一样的表结构。

[root@db01 tools]# mysqlfrm   --diagnostic /data/3306/data/world
# WARNING: Cannot generate character set or collation names without the --server option.
# CAUTION: The diagnostic mode is a best-effort parse of the .frm file. As such, it may not identify all of the components of the table correctly. This is especially true for damaged files. It will also not read the default values for the columns and the resulting statement may not be syntactically correct.
# Reading .frm file for /data/3306/data/world/city.frm:
# The .frm file is a TABLE.
# CREATE TABLE Statement:

CREATE TABLE `world`.`city` (
  `ID` int(11) NOT NULL AUTO_INCREMENT,
  `Name` char(35) NOT NULL,
  `CountryCode` char(3) NOT NULL,
  `District` char(20) NOT NULL,
  `Population` int(11) NOT NULL,
PRIMARY KEY `PRIMARY` (`ID`),
KEY `CountryCode` (`CountryCode`)
) ENGINE=InnoDB;

# Reading .frm file for /data/3306/data/world/country.frm:
# The .frm file is a TABLE.
# CREATE TABLE Statement:

CREATE TABLE `world`.`country` (
  `Code` char(3) NOT NULL,
  `Name` char(52) NOT NULL,
  `Continent` enum('Asia','Europe','North America','Africa','Oceania','Antarctica','South America') NOT NULL,
  `Region` char(26) NOT NULL,
  `SurfaceArea` float(10,2) NOT NULL,
  `IndepYear` smallint(6) DEFAULT NULL,
  `Population` int(11) NOT NULL,
  `LifeExpectancy` float(3,1) DEFAULT NULL,
  `GNP` float(10,2) DEFAULT NULL,
  `GNPOld` float(10,2) DEFAULT NULL,
  `LocalName` char(45) NOT NULL,
  `GovernmentForm` char(45) NOT NULL,
  `HeadOfState` char(60) DEFAULT NULL,
  `Capital` int(11) DEFAULT NULL,
  `Code2` char(2) NOT NULL,
PRIMARY KEY `PRIMARY` (`Code`)
) ENGINE=InnoDB;

# Reading .frm file for /data/3306/data/world/countrylanguage.frm:
# The .frm file is a TABLE.
# CREATE TABLE Statement:

CREATE TABLE `world`.`countrylanguage` (
  `CountryCode` char(3) NOT NULL,
  `Language` char(30) NOT NULL,
  `IsOfficial` enum('T','F') NOT NULL,
  `Percentage` float(4,1) NOT NULL,
PRIMARY KEY `PRIMARY` (`CountryCode`,`Language`),
KEY `CountryCode` (`CountryCode`)
) ENGINE=InnoDB;

#...done.
[root@db01 tools]#

第二步在新数据库中新建表结构(如果没有相应的库,也要先建立数据库)

mysql> create database  world;
Query OK, 1 row affected (0.00 sec)

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
| world              |
+--------------------+
5 rows in set (0.00 sec)
mysql> use world
Database changed
mysql> show  tables;
Empty set (0.00 sec)

第三步导入数据库的建表语句,得到相同的表结构
PS:如果表比较多的话建议使用concat方式拼接语句,批量创建。

mysql> CREATE TABLE `world`.`city` (
    ->   `ID` int(11) NOT NULL AUTO_INCREMENT,
    ->   `Name` char(35) NOT NULL,
    ->   `CountryCode` char(3) NOT NULL,
    ->   `District` char(20) NOT NULL,
    ->   `Population` int(11) NOT NULL,
    -> PRIMARY KEY `PRIMARY` (`ID`),
    -> KEY `CountryCode` (`CountryCode`)
    -> ) ENGINE=InnoDB;
Query OK, 0 rows affected (0.01 sec)

mysql> CREATE TABLE `world`.`country` (
    ->   `Code` char(3) NOT NULL,
    ->   `Name` char(52) NOT NULL,
    ->   `Continent` enum('Asia','Europe','North America','Africa','Oceania','Antarctica','South America') NOT NULL,
    ->   `Region` char(26) NOT NULL,
    ->   `SurfaceArea` float(10,2) NOT NULL,
    ->   `IndepYear` smallint(6) DEFAULT NULL,
    ->   `Population` int(11) NOT NULL,
    ->   `LifeExpectancy` float(3,1) DEFAULT NULL,
    ->   `GNP` float(10,2) DEFAULT NULL,
    ->   `GNPOld` float(10,2) DEFAULT NULL,
    ->   `LocalName` char(45) NOT NULL,
    ->   `GovernmentForm` char(45) NOT NULL,
    ->   `HeadOfState` char(60) DEFAULT NULL,
    ->   `Capital` int(11) DEFAULT NULL,
    ->   `Code2` char(2) NOT NULL,
    -> PRIMARY KEY `PRIMARY` (`Code`)
    -> ) ENGINE=InnoDB;
Query OK, 0 rows affected (0.01 sec)

mysql>
mysql>
mysql> CREATE TABLE `world`.`countrylanguage` (
    ->   `CountryCode` char(3) NOT NULL,
    ->   `Language` char(30) NOT NULL,
    ->   `IsOfficial` enum('T','F') NOT NULL,
    ->   `Percentage` float(4,1) NOT NULL,
    -> PRIMARY KEY `PRIMARY` (`CountryCode`,`Language`),
    -> KEY `CountryCode` (`CountryCode`)
    -> ) ENGINE=InnoDB;
Query OK, 0 rows affected (0.01 sec)

查看一下

mysql> show  tables;
+-----------------+
| Tables_in_world |
+-----------------+
| city            |
| country         |
| countrylanguage |
+-----------------+
3 rows in set (0.00 sec)

第四步单独删除空的表空间文件(删除的是独立表的空间)(保留t100w的frm,ibdata1中关于系统的数据信息)

mysql>
mysql>
mysql> alter  table   city discard  tablespace;
Query OK, 0 rows affected (0.01 sec)

mysql> alter  table   country discard  tablespace;
Query OK, 0 rows affected (0.00 sec)

mysql> alter  table   countrylanguage discard  tablespace;
Query OK, 0 rows affected (0.01 sec)

第五步将源数据库表的ibd文件拷贝到目标库底下并设置权限

[root@db01 world]# cp  *.ibd  /data/3308/data/world/
[root@db01 world]# chown  -R  mysql. /data/

第六步在目标库将ibd文件导入表空间

mysql>
mysql>
mysql> alter  table  world.city import  tablespace;
Query OK, 0 rows affected, 1 warning (0.02 sec)

mysql> alter  table  world.country import  tablespace;
Query OK, 0 rows affected, 1 warning (0.01 sec)

mysql> alter  table  world.countrylanguage import  tablespace;
Query OK, 0 rows affected, 1 warning (0.02 sec)

查看一下是否成功

mysql> select count(*) from world.city;
+----------+
| count(*) |
+----------+
|     4079 |
+----------+
1 row in set (0.00 sec)

至此已经恢复业务库数据到一个新的数据库中。

更多推荐