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達成此目的,聽起來也是可行的。 我是一介懶人就不嘗試了,有興趣餘力的大佬可以試試。