MySQL数据块损坏的恢复

数据页损坏
常规情况下如数据库出现坏块,如果数据库出现极端情况导致innodb_force_recovery=6,无法恢复,需要直接读取ibd 文件数据进行恢复,因此整体的恢复思路是把数据从ibd 读取出来,恢复到另外一个实例中

1.创建测试表

mysql> create table student(stu_id int(12),stu_name varchar(20));
Query OK, 0 rows affected (0.06 sec)
mysql> DELIMITER $
mysql> CREATE PROCEDURE proc_initData()
    -> BEGIN
    ->     DECLARE i INT DEFAULT 1;
    ->     WHILE i<=10000 DO ->         INSERT INTO student (stu_id,stu_name) VALUES(i,concat("张三",i));
    ->         SET i = i+1;
    ->     END WHILE;
    -> END $
Query OK, 0 rows affected (0.01 sec)

mysql> DELIMITER ;
mysql> CALL proc_initData();
Query OK, 1 row affected (4 min 3.81 sec)

mysql> commit;
Query OK, 0 rows affected (0.00 sec)

mysql> select count(*) from student;
+----------+
| count(*) |
+----------+
|    10000 |
+----------+
1 row in set (0.01 sec)

2.标记某个数据块为坏块

[root@localhost soft]# ./bcview /mysqldata/mysql/test/student.ibd 16 0 4
******************************************************************
This Tool Is Uesed For Find The Data In Binary format(Hexadecimal)
Usage:./bcview file blocksize offset cnt-bytes!
file: Is Your File Will To Find Data!
blocksize: Is N kb Block.Eg: 8 Is 8 Kb Blocksize(Oracle)!
                         Eg: 16 Is 16 Kb Blocksize(Innodb)!
offset:Is Every Block Offset Your Want Start!
cnt-bytes:Is After Offset,How Bytes Your Want Gets!
Edtor QQ:22389860!
Used gcc version 4.1.2 20080704 (Red Hat 4.1.2-46)
******************************************************************
----Current file size is :0.515625 Mb
----Current use set blockszie is 16 Kb
----Current file name is /mysqldata/mysql/test/student.ibd
current block:00000000--Offset:00000--cnt bytes:04--data is:808a1848
current block:00000001--Offset:00000--cnt bytes:04--data is:7e4a1bda
current block:00000002--Offset:00000--cnt bytes:04--data is:edb00808
current block:00000003--Offset:00000--cnt bytes:04--data is:572aacd7
current block:00000004--Offset:00000--cnt bytes:04--data is:c8d8b056
current block:00000005--Offset:00000--cnt bytes:04--data is:a216e84e
current block:00000006--Offset:00000--cnt bytes:04--data is:3c61ba87
current block:00000007--Offset:00000--cnt bytes:04--data is:f029a1f5
current block:00000008--Offset:00000--cnt bytes:04--data is:100e39cc
current block:00000009--Offset:00000--cnt bytes:04--data is:076fb5f1
current block:00000010--Offset:00000--cnt bytes:04--data is:7274b593
current block:00000011--Offset:00000--cnt bytes:04--data is:db3e0380
current block:00000012--Offset:00000--cnt bytes:04--data is:4ba9595f
current block:00000013--Offset:00000--cnt bytes:04--data is:614beb2e
current block:00000014--Offset:00000--cnt bytes:04--data is:6d3eafa2
current block:00000015--Offset:00000--cnt bytes:04--data is:02aa16e8
current block:00000016--Offset:00000--cnt bytes:04--data is:9d89e9d8
current block:00000017--Offset:00000--cnt bytes:04--data is:6df78bcf
current block:00000018--Offset:00000--cnt bytes:04--data is:2bacdd4d
current block:00000019--Offset:00000--cnt bytes:04--data is:5aec928c
current block:00000020--Offset:00000--cnt bytes:04--data is:f8645813
current block:00000021--Offset:00000--cnt bytes:04--data is:6fe5578f
current block:00000022--Offset:00000--cnt bytes:04--data is:9bfdc9da
current block:00000023--Offset:00000--cnt bytes:04--data is:02cf14da
current block:00000024--Offset:00000--cnt bytes:04--data is:428d4784
current block:00000025--Offset:00000--cnt bytes:04--data is:b2ef644d
current block:00000026--Offset:00000--cnt bytes:04--data is:7759cc93
current block:00000027--Offset:00000--cnt bytes:04--data is:a68e54f6
current block:00000028--Offset:00000--cnt bytes:04--data is:711ad7b5
current block:00000029--Offset:00000--cnt bytes:04--data is:d5c3ea4b
current block:00000030--Offset:00000--cnt bytes:04--data is:b0dfed41
current block:00000031--Offset:00000--cnt bytes:04--data is:ebb3250c
current block:00000032--Offset:00000--cnt bytes:04--data is:00000000
[root@localhost soft]# ./bctool /mysqldata/mysql/test/student.ibd 2 0 11111111
******************************************************************
This tool is uesed to check data ues binary format,no Big-Endian
or Little-Endian diff,this tool is base one byte on byte to change
!block is 16k.if want change other block eg:8k! please set blocks
0 and offset blocks*8192+offset!
usage:./bctool yfile blocks offset yourdata(XX)!
Warings:backup file frist!!!!!!!!!
Editor QQ:22389860
Ues gcc version 4.1.2 20080704 (Red Hat 4.1.2-46)
******************************************************************
11-11-11-11

重启mysql服务

2024-03-19T07:07:20.192633Z 0 [ERROR] InnoDB: Database page corruption on disk or a failed file read of page [page id: space=51, page number=2]. You may have to recover from a backup.
2024-03-19T07:07:20.192684Z 0 [Note] InnoDB: Page dump in ascii and hex (16384 bytes):
 len 16384; hex 11111111000000020000000000000000000000000089ae2b0003000000000000000000000033ffffffff2024-03-19T07:07:20.193910Z 0 [Note] Failed to start slave threads for channel ''
0000ffffffff000000000000000000010000000000000000ffffffff0000ffffffff000000000000ffffffff0000ffffffff000000000000ffffffff0000ffffffff000005d669d200000003ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000020000000000000000ffffffff0000ffffffff000000000000ffffffff0000ffffffff000000000000ffffffff0000ffffffff000005d669d20000000400000005000000060000000700000008000000090000000a0000000b0000000c0000000d0000000e0000000f000000100000001100000012000000130000001400000015000000160000001700000018000000190000001a0000001b0000001c0000001d0000001e0000001fffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002024-03-19T07:07:20.211011Z 0 [Note] Event Scheduler: Loaded 0 events

扫描数据字典文件
一般情况下表结构是存储在frm 文件中,drop table 会删除frm 文件,还好我们可以从innodb 系统表里读取一些信息恢复表结构。innodb 系统表有SYS_COLUMNS | SYS_FIELDS |SYS_INDEXES | SYS_TABLES。需要从系统表中恢复,而系统表是保存在$datadir/ibdata1 文件中的解析ibdata 文件,扫描出所有符合innodb 格式的数据页,结果会按照index_id 进行重新组织

[root@localhost undrop-for-innodb-master]# ./stream_parser -f /mysqldata/mysql/ibdata1
Opening file: /mysqldata/mysql/ibdata1
File information:

ID of device containing file:        64768
inode number:                      4591360
protection:                         100640 (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:         151560
Opening file: /mysqldata/mysql/ibdata1
File information:

ID of device containing file:        64768
inode number:                      4591360
protection:                         100640 (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:         151560
time of last access:            1710832037 Tue Mar 19 15:07:17 2024
time of last modification:      1710832037 Tue Mar 19 15:07:17 2024
time of last status change:     1710832037 Tue Mar 19 15:07:17 2024
total size, in bytes:             77594624 (74.000 MiB)

Size to process:                  77594624 (74.000 MiB)
time of last access:            1710832037 Tue Mar 19 15:07:17 2024
time of last modification:      1710832037 Tue Mar 19 15:07:17 2024
time of last status change:     1710832037 Tue Mar 19 15:07:17 2024
total size, in bytes:             77594624 (74.000 MiB)

Size to process:                  77594624 (74.000 MiB)
Opening file: /mysqldata/mysql/ibdata1
File information:

ID of device containing file:        64768
inode number:                      4591360
protection:                         100640 (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:         151560
Opening file: /mysqldata/mysql/ibdata1
File information:

ID of device containing file:        64768
inode number:                      4591360
protection:                         100640 (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:         151560
time of last access:            1710832037 Tue Mar 19 15:07:17 2024
time of last modification:      1710832037 Tue Mar 19 15:07:17 2024
time of last status change:     1710832037 Tue Mar 19 15:07:17 2024
total size, in bytes:             77594624 (74.000 MiB)

Size to process:                  77594624 (74.000 MiB)
time of last access:            1710832037 Tue Mar 19 15:07:17 2024
time of last modification:      1710832037 Tue Mar 19 15:07:17 2024
time of last status change:     1710832037 Tue Mar 19 15:07:17 2024
total size, in bytes:             77594624 (74.000 MiB)

Size to process:                  77594624 (74.000 MiB)
All workers finished in 0 sec

扫描数据文件

[root@localhost undrop-for-innodb-master]# ./stream_parser -f /mysqldata/mysql/test/student.ibd
Opening file: /mysqldata/mysql/test/student.ibd
File information:

ID of device containing file:        64768
inode number:                    139912091
protection:                         100640 (regular file)
number of hard links:                    1
user ID of owner:                       27
Opening file: /mysqldata/mysql/test/student.ibd
group ID of owner:                      27
device ID (if special file):             0
blocksize for filesystem I/O:         4096
File information:

number of blocks allocated:           1064
ID of device containing file:        64768
inode number:                    139912091
protection:                         100640 (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:           1064
time of last access:            1710832027 Tue Mar 19 15:07:07 2024
time of last modification:      1710832014 Tue Mar 19 15:06:54 2024
time of last status change:     1710832014 Tue Mar 19 15:06:54 2024
total size, in bytes:               540672 (528.000 kiB)

time of last access:            1710832027 Tue Mar 19 15:07:07 2024
time of last modification:      1710832014 Tue Mar 19 15:06:54 2024
Size to process:                    540672 (528.000 kiB)
time of last status change:     1710832014 Tue Mar 19 15:06:54 2024
total size, in bytes:               540672 (528.000 kiB)

Size to process:                    540672 (528.000 kiB)
Opening file: /mysqldata/mysql/test/student.ibd
File information:

ID of device containing file:        64768
inode number:                    139912091
protection:                         100640 (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:           1064
Opening file: /mysqldata/mysql/test/student.ibd
File information:

ID of device containing file:        64768
inode number:                    139912091
protection:                         100640 (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:           1064
time of last access:            1710832027 Tue Mar 19 15:07:07 2024
time of last modification:      1710832014 Tue Mar 19 15:06:54 2024
time of last status change:     1710832014 Tue Mar 19 15:06:54 2024
total size, in bytes:               540672 (528.000 kiB)

Size to process:                    540672 (528.000 kiB)
time of last access:            1710832027 Tue Mar 19 15:07:07 2024
time of last modification:      1710832014 Tue Mar 19 15:06:54 2024
time of last status change:     1710832014 Tue Mar 19 15:06:54 2024
total size, in bytes:               540672 (528.000 kiB)

Size to process:                    540672 (528.000 kiB)
All workers finished in 0 sec

获取table_id

[root@localhost undrop-for-innodb-master]# ./c_parser -4f pages-ibdata1/FIL_PAGE_INDEX/0000000000000001.page -t dictionary/SYS_TABLES.sql | grep student
SET FOREIGN_KEY_CHECKS=0;
LOAD DATA LOCAL INFILE '/undrop-for-innodb-master/dumps/default/SYS_TABLES' REPLACE INTO TABLE `SYS_TABLES` FIELDS TERMINATED BY '\t' OPTIONALLY ENCLOSED BY '"' LINES STARTING BY 'SYS_TABLES\t' (`NAME`, `ID`, `N_COLS`, `TYPE`, `MIX_ID`, `MIX_LEN`, `CLUSTER_NAME`, `SPACE`);
000000004808    A80000011B0110  SYS_TABLES      "test/student"  63      2       33      0       80      ""      51

获取index_id
[root@localhost undrop-for-innodb-master]# ./c_parser -4f pages-ibdata1/FIL_PAGE_INDEX/0000000000000003.page -t dictionary/SYS_INDEXES.sql | grep 63
SET FOREIGN_KEY_CHECKS=0;
LOAD DATA LOCAL INFILE '/undrop-for-innodb-master/dumps/default/SYS_INDEXES' REPLACE INTO TABLE `SYS_INDEXES` FIELDS TERMINATED BY '\t' OPTIONALLY ENCLOSED BY '"' LINES STARTING BY 'SYS_INDEXES\t' (`TABLE_ID`, `ID`, `NAME`, `N_FIELDS`, `TYPE`, `SPACE`, `PAGE_NO`);
000000004808    A80000011B0166  SYS_INDEXES     63      52      "GEN\_CLUST\_INDEX"     0       1       51      3

解析获得ddl 语句

[root@localhost scripts-2.7]# mysqlfrm --diagnostic /mysqldata/mysql/test/student.frm |grep -v "^#"

CREATE TABLE `test`.`student` (
  `stu_id` int(12) DEFAULT NULL,
  `stu_name` varchar(80) DEFAULT NULL
) ENGINE=InnoDB;

[root@localhost tmp]# vi student.sql
CREATE TABLE `student` (
  `stu_id` int(12) DEFAULT NULL,
  `stu_name` varchar(80) DEFAULT NULL
) ENGINE=InnoDB;

解析对应的page 页数据
请注意表结构中不要带有中文和schema_name

[root@localhost undrop-for-innodb-master]# ./c_parser -6f  pages-student.ibd/FIL_PAGE_INDEX/0000000000000052.page -t /tmp/student.sql > dumps/default/student 2> dumps/default/student.sql

[root@localhost undrop-for-innodb-master]# more dumps/default/student.sql
SET FOREIGN_KEY_CHECKS=0;
LOAD DATA LOCAL INFILE '/undrop-for-innodb-master/dumps/default/student' REPLACE INTO TABLE `student` FIELDS TERMINATED BY '\t' OPTIONALLY ENCLOSED BY '"' LINES STARTING BY 'student\t' (`stu_id`, `stu_name`);
[root@localhost undrop-for-innodb-master]# more dumps/default/student
-- Page id: 9, Format: COMPACT, Records list: Valid, Expected records: (376 376)
0000000039B4    0000000050CD    C5000001770110  student 1717    "张三1717"
0000000039B5    0000000050CE    C6000001780110  student 1718    "张三1718"
0000000039B6    0000000050CF    C7000001790110  student 1719    "张三1719"
0000000039B7    0000000050D0    C80000017A0110  student 1720    "张三1720"
0000000039B8    0000000050D1    C90000017B0110  student 1721    "张三1721"
0000000039B9    0000000050D2    CA000001540110  student 1722    "张三1722"
0000000039BA    0000000050D3    CB000001550110  student 1723    "张三1723"
0000000039BB    0000000050D4    CC000001560110  student 1724    "张三1724"
0000000039BC    0000000050D5    CD000001570110  student 1725    "张三1725"
0000000039BD    0000000050D6    CE000001580110  student 1726    "张三1726"
0000000039BE    0000000050D7    CF000001590110  student 1727    "张三1727"
0000000039BF    0000000050D8    D00000015A0110  student 1728    "张三1728"
0000000039C0    0000000050D9    D10000015B0110  student 1729    "张三1729"
0000000039C1    0000000050DA    D20000015C0110  student 1730    "张三1730"
0000000039C2    0000000050DB    D30000015D0110  student 1731    "张三1731"
0000000039C3    0000000050DC    D40000015E0110  student 1732    "张三1732"
0000000039C4    0000000050DD    D50000015F0110  student 1733    "张三1733"
0000000039C5    0000000050DE    D60000017C0110  student 1734    "张三1734"
0000000039C6    0000000050DF    D70000017D0110  student 1735    "张三1735"
0000000039C7    0000000050E0    D80000017E0110  student 1736    "张三1736"
0000000039C8    0000000050E1    D90000017F0110  student 1737    "张三1737"
0000000039C9    0000000050E2    DA000001610110  student 1738    "张三1738"
0000000039CA    0000000050E3    DB000001800110  student 1739    "张三1739"
0000000039CB    0000000050E4    DC000001630110  student 1740    "张三1740"
0000000039CC    0000000050E5    DD000001810110  student 1741    "张三1741"
0000000039CD    0000000050E6    DE000001820110  student 1742    "张三1742"
0000000039CE    0000000050E7    DF000001830110  student 1743    "张三1743"
0000000039CF    0000000050E8    E0000001840110  student 1744    "张三1744"
0000000039D0    0000000050E9    E1000001850110  student 1745    "张三1745"
0000000039D1    0000000050EA    E2000001860110  student 1746    "张三1746"
0000000039D2    0000000050EB    E3000001870110  student 1747    "张三1747"
0000000039D3    0000000050EC    E4000001880110  student 1748    "张三1748"
0000000039D4    0000000050ED    E5000001890110  student 1749    "张三1749"
0000000039D5    0000000050EE    E60000018A0110  student 1750    "张三1750"
0000000039D6    0000000050EF    E70000018B0110  student 1751    "张三1751"
0000000039D7    0000000050F0    E80000018C0110  student 1752    "张三1752"
0000000039D8    0000000050F1    E90000018D0110  student 1753    "张三1753"
0000000039D9    0000000050F2    EA0000018E0110  student 1754    "张三1754"
0000000039DA    0000000050F3    EB0000018F0110  student 1755    "张三1755"
0000000039DB    0000000050F4    EC000001900110  student 1756    "张三1756"
0000000039DC    0000000050F5    ED000001910110  student 1757    "张三1757"
0000000039DD    0000000050F6    EE000001920110  student 1758    "张三1758"
0000000039DE    0000000050F7    EF000001930110  student 1759    "张三1759"
0000000039DF    0000000050F8    F0000001940110  student 1760    "张三1760"
0000000039E0    0000000050F9    F1000001950110  student 1761    "张三1761"
0000000039E1    0000000050FA    F2000001960110  student 1762    "张三1762"
0000000039E2    0000000050FB    F3000001970110  student 1763    "张三1763"
0000000039E3    0000000050FC    F4000001990110  student 1764    "张三1764"
0000000039E4    0000000050FD    F50000019A0110  student 1765    "张三1765"
0000000039E5    0000000050FE    F60000019B0110  student 1766    "张三1766"
0000000039E6    0000000050FF    F70000019C0110  student 1767    "张三1767"
0000000039E7    000000005100    F80000019D0110  student 1768    "张三1768"
0000000039E8    000000005101    F90000019E0110  student 1769    "张三1769"
0000000039E9    000000005102    FA0000019F0110  student 1770    "张三1770"
0000000039EA    000000005103    FB000001A00110  student 1771    "张三1771"
0000000039EB    000000005104    FC000001A10110  student 1772    "张三1772"
0000000039EC    000000005105    FD000001A20110  student 1773    "张三1773"
0000000039ED    000000005106    FE000001A30110  student 1774    "张三1774"
0000000039EE    000000005107    FF000001A40110  student 1775    "张三1775"
0000000039EF    000000005108    800000010D0110  student 1776    "张三1776"
0000000039F0    000000005109    A1000001120110  student 1777    "张三1777"

数据导入

[root@localhost tmp]# scp student.sql root@10.138.130.250:/
The authenticity of host '10.138.130.250 (10.138.130.250)' can't be established.
ECDSA key fingerprint is 7f:1f:9a:0f:8b:d1:e0:17:32:08:12:73:d8:1d:9c:da.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '10.138.130.250' (ECDSA) to the list of known hosts.
root@10.138.130.250's password:
student.sql                                                                                                                                                                                              100%  116     0.1KB/s   00:00
[root@localhost tmp]# scp /undrop-for-innodb-master/dumps/default/student* root@10.138.130.250:/
root@10.138.130.250's password:
student                                                                                                                                                                                                  100% 1699KB   1.7MB/s   00:00
student.sql                                                                                                                                                                                              100%  235     0.2KB/s   00:00
[root@localhost tmp]#
mysql> source /mysqldata/student.sql
Query OK, 0 rows affected (0.00 sec)

Query OK, 25828 rows affected (0.28 sec)
Records: 25828  Deleted: 0  Skipped: 0  Warnings: 0

mysql> select count(*) from student;
+----------+
| count(*) |
+----------+
|    25828 |
+----------+
1 row in set (0.01 sec)

比损坏之前多了一万多条记录。

mysql> select count(distinct stu_id,stu_name) from student;
+---------------------------------+
| count(distinct stu_id,stu_name) |
+---------------------------------+
|                           10000 |
+---------------------------------+
1 row in set (0.03 sec)

mysql> select * from student where stu_id=1;
+--------+----------+
| stu_id | stu_name |
+--------+----------+
|      1 | 张三1    |
+--------+----------+
1 row in set (0.02 sec)

mysql> select * from student where stu_id=2;
+--------+----------+
| stu_id | stu_name |
+--------+----------+
|      2 | 张三2    |
+--------+----------+
1 row in set (0.01 sec)

mysql> select * from student where stu_id=100;
+--------+-----------+
| stu_id | stu_name  |
+--------+-----------+
|    100 | 张三100   |
+--------+-----------+
1 row in set (0.02 sec)

mysql> select * from student where stu_id=1800;
+--------+------------+
| stu_id | stu_name   |
+--------+------------+
|   1800 | 张三1800   |
|   1800 | 张三1800   |
+--------+------------+
2 rows in set (0.02 sec)

也就是标记为损坏的数据块所存储的记录在解析时出现了重复。将重复记录删除掉就可以恢复到损坏状态。

发表评论

电子邮件地址不会被公开。