恢复表结构
此文档适用于.frm文件丢失,并且没有备份情况下恢复出建表语句
恢复InnoDB字典表
首先创建用于恢复的字典辅助表1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16mysql> create database sakila_recovered;
Query OK, 1 row affected (0.01 sec)
[mysql@master undrop-for-innodb]$ cat dictionary/SYS_* | mysql -umysql -pmysql -S /data/mysqldata/3307/mysql.sock sakila_recovered
Warning: Using a password on the command line interface can be insecure.
mysql> show tables;
+----------------------------+
| Tables_in_sakila_recovered |
+----------------------------+
| SYS_COLUMNS |
| SYS_FIELDS |
| SYS_INDEXES |
| SYS_TABLES |
+----------------------------+
4 rows in set (0.00 sec)
字典表存储在ibdata1中,所以要解析它1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60[mysql@master undrop-for-innodb]$ ./stream_parser -f /data/mysqldata/3307/data/ibdata1
Opening file: /data/mysqldata/3307/data/ibdata1
File information:
ID of device containing file: 64768
inode number: 104900755
protection: 100660 (regular file)
number of hard links: 1
user ID of owner: 27
group ID of owner: 27
device ID (if special file): 0
blocksize for filesystem I/O: 4096
number of blocks allocated: 4194304
time of last access: 1482819237 Tue Dec 27 14:13:57 2016
time of last modification: 1482819237 Tue Dec 27 14:13:57 2016
time of last status change: 1482819237 Tue Dec 27 14:13:57 2016
total size, in bytes: 2147483648 (2.000 GiB)
Size to process: 2147483648 (2.000 GiB)
Worker(0): 5.47% done. 2016-12-27 14:24:21 ETA(in 00:00:18). Processing speed: 104.000 MiB/sec
Worker(0): 13.67% done. 2016-12-27 14:24:14 ETA(in 00:00:10). Processing speed: 168.000 MiB/sec
Worker(0): 22.66% done. 2016-12-27 14:24:13 ETA(in 00:00:08). Processing speed: 184.000 MiB/sec
Worker(0): 28.52% done. 2016-12-27 14:24:18 ETA(in 00:00:12). Processing speed: 120.000 MiB/sec
Worker(0): 35.94% done. 2016-12-27 14:24:15 ETA(in 00:00:08). Processing speed: 152.000 MiB/sec
Worker(0): 43.75% done. 2016-12-27 14:24:15 ETA(in 00:00:07). Processing speed: 160.000 MiB/sec
Worker(0): 51.17% done. 2016-12-27 14:24:15 ETA(in 00:00:06). Processing speed: 152.000 MiB/sec
Worker(0): 57.81% done. 2016-12-27 14:24:16 ETA(in 00:00:06). Processing speed: 136.000 MiB/sec
Worker(0): 64.45% done. 2016-12-27 14:24:16 ETA(in 00:00:05). Processing speed: 136.000 MiB/sec
Worker(0): 71.48% done. 2016-12-27 14:24:16 ETA(in 00:00:04). Processing speed: 144.000 MiB/sec
Worker(0): 78.91% done. 2016-12-27 14:24:15 ETA(in 00:00:02). Processing speed: 152.000 MiB/sec
Worker(0): 85.16% done. 2016-12-27 14:24:16 ETA(in 00:00:02). Processing speed: 128.000 MiB/sec
Worker(0): 92.19% done. 2016-12-27 14:24:16 ETA(in 00:00:01). Processing speed: 144.000 MiB/sec
All workers finished in 13 sec
Data from database pages is saved by the stream_parser to folder pages-ibdata1:
[mysql@master undrop-for-innodb]$ tree pages-ibdata1/
pages-ibdata1/
├── FIL_PAGE_INDEX
│ ├── 0000000000000001.page
│ ├── 0000000000000002.page
│ ├── 0000000000000003.page
│ ├── 0000000000000004.page
│ ├── 0000000000000005.page
│ ├── 0000000000000011.page
│ ├── 0000000000000012.page
│ ├── 0000000000000013.page
│ ├── 0000000000000014.page
│ ├── 0000000000000015.page
│ ├── 0000000000000016.page
│ ├── 0000000000000017.page
│ ├── 0000000000000018.page
│ ├── 0000000000000019.page
│ ├── 0000000000000020.page
│ ├── 0000000000000021.page
│ ├── 0000000000000022.page
│ ├── 0000000000000023.page
│ └── 18446744069414584320.page
└── FIL_PAGE_TYPE_BLOB
2 directories, 19 files
现在我们要从生成的page文件中抽取字典记录,我们县创建一个目录1
mkdir -p dumps/default
And now we can generate table dumps and LOAD INFILE commands to load the dumps. We also need to specify -D option to c_parser because the records we need were deleted from the dictionary when the table was dropped.
现在开始恢复字典表
SYS_TABLES1
2
3
4./c_parser -4Df pages-ibdata1/FIL_PAGE_INDEX/0000000000000001.page \
-t dictionary/SYS_TABLES.sql \
> dumps/default/SYS_TABLES \
2> dumps/default/SYS_TABLES.sql
SYS_INDEXES1
2
3
4./c_parser -4Df pages-ibdata1/FIL_PAGE_INDEX/0000000000000003.page \
-t dictionary/SYS_INDEXES.sql \
> dumps/default/SYS_INDEXES \
2> dumps/default/SYS_INDEXES.sql
SYS_COLUMNS1
2
3
4./c_parser -4Df pages-ibdata1/FIL_PAGE_INDEX/0000000000000002.page \
-t dictionary/SYS_COLUMNS.sql \
> dumps/default/SYS_COLUMNS \
2> dumps/default/SYS_COLUMNS.sql
SYS_FIELDS1
2
3
4./c_parser -4Df pages-ibdata1/FIL_PAGE_INDEX/0000000000000004.page \
-t dictionary/SYS_FIELDS.sql \
> dumps/default/SYS_FIELDS \
2> dumps/default/SYS_FIELDS.sql
生成了包含数据的文件和包含load data infile语句的sql文件1
2
3[mysql@master undrop-for-innodb]$ ls dumps/default/
SYS_COLUMNS SYS_FIELDS SYS_INDEXES SYS_TABLES
SYS_COLUMNS.sql SYS_FIELDS.sql SYS_INDEXES.sql SYS_TABLES.sql
恢复字典表数据
cat dumps/default/*.sql | mysql -umysql -pmysql -S /data/mysqldata/3307/mysql.sock sakila_recovered
编译sys_parser
sys_parser is a tool that reads dictionary from tables stored in MySQL and generates CREATE TABLE structure for a table.
To compile it we will need MySQL libraries and development files. Depending on a distribution they may be in -devel or -dev package. On RedHat based system you can check it with command yum provides “*/mysql_config” . On my server it was package mysql-community-devel.
If all necessary packages are installed compilation boils down to simple command:1
2
3[mysql@master undrop-for-innodb]$ make sys_parser
/usr/local/mysql/bin/mysql_config
cc -o sys_parser sys_parser.c `mysql_config --cflags` `mysql_config --libs`
恢复表结构
1 | [mysql@master undrop-for-innodb]$ ./sys_parser -u mysql -p mysql -d sakila_recovered sakila/actor |
遗憾的是好像sys_parser不能指定sock,只能用默认端口号3306
还有一些注意事项:
1.InnoDB不存储您可以在frm文件中找到的所有信息。 例如,如果一个字段是AUTO_INCREMENT,InnoDB字典什么也不知道。因此,sys_parser将不会恢复该属性。 如果有任何字段或表级注释,他们将丢失
2.sys_parser生成适合进一步数据恢复的表结构。 它可以但不会恢复二级索引,外键。
3.InnoDB不存储DECIMAL类型作为二进制字符串。 它不存储DECIMAL字段的精度。 这样信息就会丢失。
For example, table payment uses DECIMAL to store money.1
2
3
4
5
6
7
8
9
10
11# ./sys_parser -u root -p qwerty -d sakila_recovered sakila/payment
CREATE TABLE `payment`(
`payment_id` SMALLINT UNSIGNED NOT NULL,
`customer_id` SMALLINT UNSIGNED NOT NULL,
`staff_id` TINYINT UNSIGNED NOT NULL,
`rental_id` INT,
`amount` DECIMAL(6,0) NOT NULL,
`payment_date` DATETIME NOT NULL,
`last_update` TIMESTAMP NOT NULL,
PRIMARY KEY (`payment_id`)
) ENGINE=InnoDB;
幸运的是,Oracle计划扩展InnoDB字典,最终摆脱了.frm文件。