Percona Data Recovery Tool for InnoDB--mysql innodb引擎表非常規修複工具

來源:互聯網
上載者:User

標籤:mysql innodb recovery

    如果線上的MySQL生產資料庫的資料被誤刪除,然後DBA去會恢複資料的時候,發現該資料庫沒有做備份、binlog也沒有開啟的話。還有其他手段去儘力去恢複資料嗎? percona公司提供了一個非常規的修複工具,可以去修複表資料。當然這個工具是有限制的:

1、僅針對innodb引擎的表2、表的row_format必須是REDUNDANT或者COMPACT,一般建議為COMPACT。而mysql5.7.8以上預設為Dynamic,這個要特別注意。3、一旦發生誤操作,需要儘快停止對事故表的寫入,將idb檔案拷貝出來。4、資料不一定總是能恢複,比如被重新寫入的情況等

    現在在虛擬機器上做下測試:

    1、先準備好測試表:

[email protected]:mysql3306.sock  15:35:  [linzj]>show create table linzj.linzj\G*************************** 1. row ***************************       Table: linzjCreate Table: CREATE TABLE `linzj` (  `INVOKE_LOG_ID` bigint(22) NOT NULL,  `INVOKE_LOG_APP_ID` varchar(255) NOT NULL COMMENT ‘調用介面應用ID‘,  `INVOKE_LOG_IPADDRESS` varchar(255) NOT NULL COMMENT ‘調用介面應用IP‘,  `INVOKE_LOG_METHOD` varchar(255) NOT NULL COMMENT ‘調用介面方式‘,  `INVOKE_LOG_STATUS` int(11) NOT NULL COMMENT ‘調用介面傳回值‘,  `INVOKE_LOG_INVOKETIME` datetime NOT NULL COMMENT ‘介面調用時間‘,  `INVOKE_LOG_PARAM1` varchar(255) DEFAULT NULL,  `INVOKE_LOG_PARAM2` varchar(255) DEFAULT NULL,  `INVOKE_LOG_PARAM3` varchar(255) DEFAULT NULL,  `INVOKE_LOG_PARAM4` varchar(255) DEFAULT NULL,  `INVOKE_LOG_PARAM5` varchar(255) DEFAULT NULL,  `INVOKE_LOG_INSTANCE_ID` varchar(255) DEFAULT NULL,  `INVOKE_LOG_COST` int(11) DEFAULT ‘0‘,  PRIMARY KEY (`INVOKE_LOG_ID`),  KEY `idx_id` (`INVOKE_LOG_ID`)) ENGINE=InnoDB DEFAULT CHARSET=utf81 row in set (0.00 sec)[email protected]:mysql3306.sock  15:36:  [linzj]>select count(*) from linzj.linzj ;+----------+| count(*) |+----------+|    10000 |+----------+1 row in set (0.00 sec)[email protected]:mysql3306.sock  16:54:  [linzj]>alter table linzj add index idx_cost(INVOKE_LOG_COST);alter table linzj add primary key pk_id(INVOKE_LOG_ID);Query OK, 0 rows affected (0.06 sec)Records: 0  Duplicates: 0  Warnings: 0[email protected]:mysql3306.sock  16:53:  [linzj]>alter table linzj row_format=COMPACT;Query OK, 0 rows affected (0.03 sec)Records: 0  Duplicates: 0  Warnings: 0[email protected]:mysql3306.sock  16:46:  [information_schema]>SELECT ROW_FORMAT from TABLES WHERE TABLE_SCHEMA=‘linzj‘ and table_name=‘linzj‘;;+------------+| ROW_FORMAT |+------------+| Compact    |+------------+1 row in set (0.10 sec)

    2、類比誤操作,將表資料清空

[email protected]:mysql3306.sock  15:37:  [linzj]>truncate table linzj.linzj;Query OK, 0 rows affected (0.11 sec)[email protected]:mysql3306.sock  15:38:  [linzj]>select count(*) from linzj.linzj ;+----------+| count(*) |+----------+|        0 |+----------+1 row in set (0.00 sec)

    3、馬上備份表的ibd檔案

[[email protected] tmp]# cp /data/mysql/mysql3306/data/linzj/linzj.* /tmp/[[email protected] tmp]# ll linzj.*-rw-r-----. 1 root root  13463 Jul 11 15:39 linzj.frm-rw-r-----. 1 root root 114688 Jul 11 15:39 linzj.ibd

    4、安裝工具

cd /usr/local/wget https://launchpad.net/percona-data-recovery-tool-for-innodb/trunk/release-0.5/+download/percona-data-recovery-tool-for-innodb-0.5.tar.gztar -xvf percona-data-recovery-tool-for-innodb-0.5.tar.gz./configuremake

    5、解析ibd檔案

[[email protected] percona-data-recovery-tool-for-innodb-0.5]# mv /tmp/linzj.ibd  ./[[email protected] percona-data-recovery-tool-for-innodb-0.5]# ./page_parser -5 -f linzj.ibd Opening file: linzj.ibd:2050            ID of device containing file781917          inode number33184           protection1               number of hard links0               user ID of owner0               group ID of owner0               device ID (if special file)114688          total size, in bytes4096            blocksize for filesystem I/O224             number of blocks allocated1499758773      time of last access1499758773      time of last modification1499759529      time of last status change114688  Size to process in bytes104857600       Disk cache size in bytes[[email protected] percona-data-recovery-tool-for-innodb-0.5]# cd pagepage_parser       page_parser.c     pages-1499759549/ [[email protected] percona-data-recovery-tool-for-innodb-0.5]# cd pagepage_parser       page_parser.c     pages-1499759549/ [[email protected] percona-data-recovery-tool-for-innodb-0.5]# cd  pages-1499759549/ [[email protected] pages-1499759549]# lltotal 4drwxr-xr-x. 4 root root 4096 Jul 11 15:52 FIL_PAGE_INDEX[[email protected] pages-1499759549]# cd FIL_PAGE_INDEX/[[email protected] FIL_PAGE_INDEX]# ls0-60  0-61

     參數解釋: -5:代表 row_format為Compact -f:代表要解析的檔案

[email protected]:mysql3306.sock  15:54:  [information_schema]>select i.INDEX_ID, i.NAME FROM INNODB_SYS_INDEXES as i INNER JOIN INNODB_SYS_TABLES as t USING(TABLE_ID) WHERE t.NAME=‘linzj/linzj‘;+----------+---------+| INDEX_ID | NAME    |+----------+---------+|       60 | PRIMARY ||       61 | idx_id  |+----------+---------+2 rows in set (0.00 sec)

    此過程會將表的idb檔案解析為很多的page,innodb的page分為兩大部分,一部分一級索引部分(primary key),另一部分為二級索引部分(secondary key),所以解析出來的idb包括了主鍵資料和索引資料兩大部分(如果該表有多個二級索引,則會產生多個檔案)

可以知道60為主鍵索引的index_id,而61為輔助索引。

    6、擷取表的定義

[[email protected] percona-data-recovery-tool-for-innodb-0.5]# ./create_defs.pl -host localhost -port 3306 -user root -password linzj -db linzj -table linzj > include/table_defs.h上面的命令會將t_bibasic_storage表的表結構定義傳入到table_defs.h中,然後重新make.[[email protected] percona-data-recovery-tool-for-innodb-0.5]# makegcc -DHAVE_OFFSET64_T -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE=1 -D_LARGEFILE_SOURCE=1 -Wall -O3 -g -I include -I mysql-source/include -I mysql-source/innobase/include -c tables_dict.c -o lib/tables_dict.ogcc -DHAVE_OFFSET64_T -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE=1 -D_LARGEFILE_SOURCE=1 -Wall -O3 -g -I include -I mysql-source/include -I mysql-source/innobase/include -c check_data.c -o lib/check_data.ogcc -DHAVE_OFFSET64_T -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE=1 -D_LARGEFILE_SOURCE=1 -Wall -O3 -g -I include -I mysql-source/include -I mysql-source/innobase/include -o constraints_parser constraints_parser.c lib/tables_dict.o lib/print_data.o lib/check_data.o lib/libut.a lib/libmystrings.agcc -DHAVE_OFFSET64_T -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE=1 -D_LARGEFILE_SOURCE=1 -Wall -O3 -g -I include -I mysql-source/include -I mysql-source/innobase/include -static -lrt -o page_parser page_parser.c lib/tables_dict.o lib/libut.a

    7、恢複表的資料

[[email protected] percona-data-recovery-tool-for-innodb-0.5]# ./constraints_parser -5 -D -f pages-1499764924/FIL_PAGE_INDEX/0-79/ > ./linzj.sqlLOAD DATA INFILE ‘/usr/local/percona-data-recovery-tool-for-innodb-0.5/dumps/default/linzj‘ REPLACE INTO TABLE `linzj` FIELDS TERMINATED BY ‘\t‘ OPTIONALLY ENCLOSED BY ‘"‘ LINES STARTING BY ‘linzj\t‘ (INVOKE_LOG_ID, INVOKE_LOG_APP_ID, INVOKE_LOG_IPADDRESS, INVOKE_LOG_METHOD, INVOKE_LOG_STATUS, INVOKE_LOG_INVOKETIME, INVOKE_LOG_PARAM1, INVOKE_LOG_PARAM2, INVOKE_LOG_PARAM3, INVOKE_LOG_PARAM4, INVOKE_LOG_PARAM5, INVOKE_LOG_INSTANCE_ID, INVOKE_LOG_COST);[[email protected] percona-data-recovery-tool-for-innodb-0.5]# vim linzj.sql linzj   9893202823      "[email protected]"       "172.16.115.7"  "authenticateUserByPassword"    0       "2017-05-01 00:00:01"   "[email protected]"      "[email protected]***"       "***n/a"        "n/a"   "172"   ".16.112.23:8080<80>    -1844313341linzj   9893202825      "[email protected]"       "172.16.115.10" "authenticateUserByPassword"    0       "2017-05-01 00:00:01"   "[email protected]"        "[email protected]***"       "***n/a"        "n/a"   "172"".16.112.40:8080<80>    -1777204477

    參數: -5 -f的參數和page_parser相同; -D:該參數的含義為代表恢複刪除的資料頁

    從sql檔案中看出,該工具有bug,對mysql5.6以上的datetime欄位類型並不支援,需要對工具做下修改。具體可以參考:https://bugs.launchpad.net/percona-data-recovery-tool-for-innodb/+bug/1190976 , 重新make後產生的sql檔案如下:

[[email protected] percona-data-recovery-tool-for-innodb-0.5]# vim linzj.sql linzj   9893202823      "[email protected]"       "172.16.115.7"  "authenticateUserByPassword"    0       "2017-05-01 00:00:01"   "[email protected]"      "[email protected]***"       "***n/a"        "n/a"   "172"   ".16.112.23:8080<80>    -1844313341linzj   9893202825      "[email protected]"       "172.16.115.10" "authenticateUserByPassword"    0       "2017-05-01 00:00:01"   "[email protected]"        "[email protected]***"       "***n/a"        "n/a"   "172"   ".16.112.40:8080<80>    -1777204477

    從中可以看出,修改了print_data.c後,已經能正常展現出datetime類型的欄位明細。但是INVOKE_LOG_INSTANCE_ID欄位填充非常規的符號導致產生的sql檔案異常,也就是說,該欄位的資訊無法修複,也導致了後面的INVOKE_LOG_COST欄位的資訊也無法修複出來。    

    8、倒回資料

[email protected]:mysql3306.sock  17:26:  [linzj]>LOAD DATA INFILE ‘/tmp/linzj.sql‘ REPLACE INTO TABLE `linzj` FIELDS TERMINATED BY ‘\t‘ OPTIONALLY ENCLOSED BY ‘"‘ LINES STARTING BY ‘linzj\t‘ (INVOKE_LOG_ID, INVOKE_LOG_APP_ID, INVOKE_LOG_IPADDRESS, INVOKE_LOG_METHOD, INVOKE_LOG_STATUS, INVOKE_LOG_INVOKETIME, INVOKE_LOG_PARAM1, INVOKE_LOG_PARAM2, INVOKE_LOG_PARAM3, INVOKE_LOG_PARAM4, INVOKE_LOG_PARAM5, INVOKE_LOG_INSTANCE_ID, INVOKE_LOG_COST);ERROR 1300 (HY000): Invalid utf8 character string: ‘".16.112.47:8080‘

    這裡的報錯就是因為INVOKE_LOG_INSTANCE_ID欄位有特殊字元導致後續欄位的資訊也無法修複出來。

    9、總結

    綜上所述,其實該工具也並非可以保證100%修複資料。所以作為一名DBA,首先要做好生產庫的資料備份,並要時不時對備份進行檢驗其有效性。只要備份在,心才不會亂。希望永遠都不會在生產庫上用上這個工具。

本文出自 “林志堅的部落格” 部落格,請務必保留此出處http://linzhijian.blog.51cto.com/1047212/1946409

Percona Data Recovery Tool for InnoDB--mysql innodb引擎表非常規修複工具

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.