mysql根據.frm和.ibd檔案恢復資料表

2023-07-27 21:01:15

忠人之事受人之託 起因是因為一位朋友的資料庫伺服器被重灌了,只剩下一個zbp_post.frm和zbp_post.ibd檔案。諮詢我能不能恢復,確實我只用過mysqldump這種工具匯出資料 然後進行恢復到資料庫。這種直接備份物理儲存檔案還沒有嘗試過。

前提是需要歷史ibd檔案的所屬資料庫版本 需要和還原新庫資料庫版本保持一致,這樣才能少踩坑。

建立表結構

要想恢復資料,表結構需要和.ibd裡面的結構保持一致,如果不一致將恢復不成功 可能會報如下錯誤。或者其他異常。

 [ERROR] InnoDB: Trying to access page number 426442752 in space 24, space name test1/zbp_post, which is outside the tablespace bounds. Byte offset 0, len 16384, i/o type read. If you get this error at mysqld startup, please check that your my.cnf matches the ibdata files that you have in the MySQL server.
獲取表結構

如果明確知道表結構 這一步可跳過。不知道表結構可從這一步操作中獲取到表結構。

藉助了mysql utilities工具來檢視表結構。

安裝mysql utilities

這裡我適用window 其他系統也是類似的操作 下載後安裝好。

https://downloads.mysql.com/archives/get/p/30/file/mysql-utilities-1.6.5-winx64.msi

其他系統下載地址 https://downloads.mysql.com/archives/

進入zbp_post.frm目錄中執行獲取表結構命令。

cd zbp_post
mysqlfrm --diagnostic ./zbp_post.frm

執行完mysqlfrm命令後 輸出如下表結構

CREATE TABLE `zbp_post` (
  `log_ID` int(11) NOT NULL AUTO_INCREMENT,
  `log_CateID` int(11) NOT NULL,
  `log_AuthorID` int(11) NOT NULL,
  `log_Tag` varchar(1000) NOT NULL,
  `log_Status` tinyint(4) NOT NULL,
  `log_Type` int(11) NOT NULL,
  `log_Alias` varchar(1000) NOT NULL,
  `log_IsTop` tinyint(4) NOT NULL,
  `log_IsLock` tinyint(4) NOT NULL,
  `log_Title` varchar(1000) NOT NULL,
  `log_Intro` text,
  `log_Content` longtext,
  `log_CreateTime` int(11) NOT NULL,
  `log_PostTime` int(11) NOT NULL,
  `log_UpdateTime` int(11) NOT NULL,
  `log_CommNums` int(11) NOT NULL,
  `log_ViewNums` int(11) NOT NULL,
  `log_Template` varchar(1000) NOT NULL,
  `log_Meta` longtext,
  `log_BdPush` int(11) NOT NULL,
PRIMARY KEY `PRIMARY` (`log_ID`),
KEY `zbp_log_TPISC` (`log_Type`,`log_PostTime`,`log_IsTop`,`log_Status`,`log_CateID`),
KEY `log_CateID` (`log_CateID`),
KEY `log_AuthorID` (`log_AuthorID`),
KEY `log_PostTime` (`log_PostTime`),
KEY `log_CommNums` (`log_CommNums`),
KEY `log_ViewNums` (`log_ViewNums`),
KEY `log_Title` (`log_Title`)
) ENGINE=InnoDB;

資料庫設定修改

編輯MySQL的組態檔,通常是my.cnf或my.ini檔案,在[mysqld]部分新增以下行:

這將確保每個表有單獨的.ibd檔案。

[mysqld]
innodb_file_per_table=1
wait_timeout=600 #600秒(10分鐘)

wait_timeout=600 這個設定可以不加 存取還原資料比較大。執行超時的情況。需要根據場景酌情設定。

開始恢復資料

建立新資料庫

建立一個資料庫 任意資料庫名。

create database test1;
建立表

進入到新建立的資料庫中(use test1),複製上一步中的表結構SQL。執行建立表結構操作。

使用.ibd檔案恢復資料到新表

解除安裝表空間 執行此步會自動刪除新表對應的.ibd檔案

ALTER TABLE zbp_post DISCARD TABLESPACE;

拷貝備份的.ibd檔案到新建立資料庫對應的目錄中。

一般目錄在mysql儲存資料庫的目錄。如我當前的伺服器mysql資料儲存的目錄在/usr/local/mysql/data,資料庫名 test1 ,表名 zbp_post。

那麼拷貝.ibd檔案的目錄為 /usr/local/mysql/data/zbp_post/test1中。

裝載表空間

ALTER TABLE zbp_post IMPORT TABLESPACE;

完成以上步驟後,您應該能夠成功還原.ibd檔案。請注意,這種方法僅適用於InnoDB引擎的表。如果.ibd檔案損壞或不匹配,可能需要使用MySQL的資料恢復工具來修復資料庫。

驗證

果然完美

mysql> select count(1) from zbp_post;
+----------+
| count(1) |
+----------+
|   785216 |
+----------+
1 row in set (0.15 sec)

如果有朋友遇到類似問題可以和我聯絡。