1. 程式人生 > >MySQL僅從.frm和.ibd檔案恢復資料

MySQL僅從.frm和.ibd檔案恢復資料

前言

MySQL的資料庫其相關檔案都會存放在安裝目錄下data資料夾下的同命資料夾中,不同的儲存引擎建立的表其檔案也不一樣,下面來認識下這些資料庫檔案。

db.opt

用來記錄該庫的預設字符集編碼和字符集排序規則用的。也就是說如果你建立資料庫指定預設字符集和排序規則,那麼後續建立的表如果沒有指定字符集和排序規則,那麼該新建的表將採用db.opt檔案中指定的屬性。

.frm

與表相關的元資料資訊都存放在.frm檔案中,主要是表結構的定義資訊,不論什麼儲存引擎,每一個表都會有一個以表名命名的.frm檔案。

.MYD和.MYI

.MYD:MY Data,是MyISAM儲存引擎專用的用於存放MyISAM表的資料; .MYI:MY Index,也是專屬於MyISAM儲存引擎的主要存放MyISAM表的索引相關資訊。

.ibd和.ibdata

兩者都是專屬於InnoDB儲存引擎的資料庫檔案。 當採用共享表空間時所有InnoDB表的資料均存放在.ibdata中,所以當表越來越多時,這個檔案會變得很大; 相對應的.ibd就是採用獨享表空間時InnoDB表的資料檔案。 修改為獨享表空間的方法是在my.ini配置檔案中新增/修改此條: Innodb_file_per_table=1 注意:筆者所用的MySQL-5.7是預設獨享表空間的,不用特意在配置檔案中新增。

當然,就算開啟了獨享表空間,.ibdata檔案也會越來越大,因為這個檔案裡還儲存了:

  • 變更緩衝區
  • 雙寫緩衝區
  • 撤銷日誌

這些東西究竟是啥玩意兒?我也不知道233

如果是MyISAM儲存引擎,直接拷貝.frm、.MYD、.MYI到新的庫資料夾下就行了,簡直方便快捷簡單易用。但現在MySQL在不配置的情況下預設的儲存引擎是InnoDB,說明它還是有優越性在的。具體兩者的差異有空另起一篇或者網上查查資料吧,三言兩語說不清楚,這裡就不展開了。 當然,能點進這篇部落格的肯定是想看InnoDB表的資料恢復,尤其是丟失了.ibdata檔案的情況下。

一、恢復表結構

首要的一件事情就是恢復表結構,如果很幸運地保留了當時的表結構,此步可跳過。

1.1 隨意建立一張同名表

CREATETABLE weibo_tweets(a int)ENGINE=InnoDB;
  • 1

1.2 關閉mysql服務

net stop mysql

1.3 複製備份的.frm覆蓋新建的表.frm

1.4 開啟mysql服務

net start mysql

1.5 在mysql安裝目錄data資料夾下用文字編輯器開啟.err檔案

這是mysql的錯誤日誌,找到諸如 2018-01-09T08:19:46.170814Z 3 [Warning] InnoDB: Table data_rec/weibo_tweets contains 1 user defined columns in InnoDB, but 6 columns in MySQL. Please check INFORMATION_SCHEMA.INNODB_SYS_COLUMNS 的記錄,發現原表擁有6個欄位。

1.6 刪除當前表,新建一張擁有6個欄位的同名表

mysql> DROP TABLE weibo_tweets;
Query OK, 0 rows affected (0.26 sec)

mysql>CREATE TABLE weibo_tweets(a1 int,a2 int,a3 int,a4 int,a5 int,a6 int)ENGINE=InnoDB;
Query OK, 0 rows affected (0.66 sec)
  • 1
  • 2
  • 3
  • 4
  • 5

1.7 重複步驟1.2-1.3

修改配置檔案my.ini在[mysqld]下新增/修改innodb_force_recovery=6

1.8 啟動mysql服務,查看錶結構,發現表結構已經恢復

mysql> desc weibo_tweets;
+-------------+---------------+------+-----+-------------------+----------------+
| Field       | Type          | Null | Key | Default           | Extra          |
+-------------+---------------+------+-----+-------------------+----------------+
| id          | int(11)       | NO   | PRI | NULL              | auto_increment |
| uid         | varchar(10)   | NO   |     | NULL              |                |
| content     | varchar(1000) | YES  |     | NULL              |                |
| pub_time    | varchar(20)   | YES  |     | NULL              |                |
| tool        | varchar(50)   | YES  |     | NULL              |                |
| create_time | datetime      | YES  |     | CURRENT_TIMESTAMP |                |
+-------------+---------------+------+-----+-------------------+----------------+
6 rows in set, 1 warning (0.01 sec)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

匯出表結構,在命令提示符下輸入 mysqldump -uroot -proot data_rec weibo_twets > e:\tweets.sql 在.sql檔案中找到建表語句。 或者也可以用資料庫管理軟體如navicat中找到這張表,在物件資訊中複製下DDL選項卡里的內容。

1.9 停止mysql服務,修改配置檔案my.ini

修改innodb_force_recovery=0或者直接註釋掉。

2.0 啟動mysql服務,刪掉這張表,用獲得的建表語句新建表

至此,表結構已經完全恢復。

二、恢復表資料

2.1 分離表空間

使當前.ibd的資料檔案和.frm分離。 ALTER TABLE weibo_tweets DISCARD TABLESPACE;

2.2 複製備份的.ibd檔案覆蓋新的表資料

2.3 重新建立新的連線

ALTER TABLE weibo_tweets IMPORT TABLESPACE; 至此,資料恢復完畢。

三、後話

網上有人用vim以16進位制開啟.ibd檔案,查看錶空間ID後,將備份.ibd檔案覆蓋後修改表空間ID為新的.ibd檔案的ID,也可以重新建立資料檔案和表空間的連線恢復資料。 Windows環境下可以用WinHex達成此目的,聽起來也是可行的。 我是一介懶人就不嘗試了,有興趣餘力的大佬可以試試。