mysql innodb 从 ibd 文件恢复表数据
最近內(nèi)部的 mysql 數(shù)據(jù)庫發(fā)生了一件奇怪的事,其中有一個(gè)表 users625 突然出現(xiàn)問題,
所有對它的操作都報(bào)錯(cuò)誤 數(shù)據(jù)表不存在。
show tables 它還顯示在列表里,在 mysql 數(shù)據(jù)目錄中也可以找到對應(yīng)的表文件,也沒有
進(jìn)行過刪除操作,突然出現(xiàn)這樣的錯(cuò)誤非常奇怪。
內(nèi)部運(yùn)行環(huán)境:
| OS | Debian Squeeze x64 |
| mysql 版本 | 5.1 |
| mysql 引擎 | innodb |
發(fā)生了什么
突然出現(xiàn)這種情況,第一反應(yīng)必定是想辦法將表中的用戶數(shù)據(jù)找回,但是目前發(fā)生問題的情況與原因都不明晰,
不能輕舉妄動(dòng)。
查看 mysql 日志,在操作出錯(cuò)的時(shí)候,日志這樣顯示:
mysqld: 180926 11:10:53 InnoDB: cannot calculate statistics for table km8/users625 mysqld: InnoDB: because the .ibd file is missing. For help, please refer to mysqld: InnoDB: http://dev.mysql.com/doc/refman/5.1/en/innodb-troubleshooting.html mysqld: 180926 11:10:53 [ERROR] MySQL is trying to open a table handle but the .ibd file for mysqld: table km8/users625 does not exist. mysqld: Have you deleted the .ibd file from the database directory under mysqld: the MySQL datadir, or have you used DISCARD TABLESPACE? mysqld: See http://dev.mysql.com/doc/refman/5.1/en/innodb-troubleshooting.html mysqld: how you can resolve the problem.其中提到3個(gè)可追溯的點(diǎn):
- ibd file
- DISCARD TABLESPACE
- http://dev.mysql.com/doc/refman/5.1/en/innodb-troubleshooting.html
了解這3點(diǎn)提到的內(nèi)容,應(yīng)該對判斷情況有很好的幫助。
ibd file
日志中提問,是否丟失了 ibd 文件?先到 mysql 數(shù)據(jù)目錄下查找,
. ├── ibdata1 ├── ....... ├── ....... └── km8├── ............├── ............├── users625.frm├── users625.ibd├── ............└── ............users625 的 ibd 文件是存在的,與之一起的還有文件 users625.frm 。
根據(jù)官方文檔對 frm 文件的描述,frm 文件是用來保存 table 表結(jié)構(gòu)(即 table 的定義)的,無論使用什么存儲引擎。
與之相對的,ibd 文件是用來存儲表數(shù)據(jù)(即行數(shù)據(jù))的,通常情況下,所有數(shù)據(jù)都會存儲在系統(tǒng)的 ibd 文件,
但是當(dāng)開啟選項(xiàng) innodb_file_per_table 的時(shí)候,每個(gè)表的數(shù)據(jù)會使用單獨(dú)的 ibd 文件來存儲。
當(dāng)前的 mysql 就開啟了這個(gè)選項(xiàng),
[mysqld] innodb_file_per_table=1目前 frm 與 ibd 文件都存在,從中恢復(fù)數(shù)據(jù)便存在一些希望。
DISCARD TABLESPACE
日志中提到的 DISCARD TABLESPACE 其實(shí)是在猜測導(dǎo)致 ibd 文件丟失的原因,因?yàn)樗鼤h除相應(yīng) table 的 ibd 文件(所謂 tablespace)。
> ALTER TABLE km8.users625 DISCARD TABLESPACE;底層的 users625.ibd 文件就會被刪除,丟失所有表數(shù)據(jù)。
根據(jù)目前情況來看, ibd 文件還存在,所以它不是導(dǎo)致錯(cuò)誤的原因。
trouble shooting doc
日志中提到的參考鏈接,其中列舉了多種情況,和當(dāng)前問題相關(guān)的是一個(gè)子鏈接,
按照它提供的方法,嘗試進(jìn)行數(shù)據(jù)恢復(fù)。
數(shù)據(jù)恢復(fù)
官方文檔提到的恢復(fù)數(shù)據(jù)的方法,思路很清晰:
我按照這種方式嘗試恢復(fù)數(shù)據(jù),并不是那么順利:
如何獲得 table 表結(jié)構(gòu)?
在第2步,需要建立同樣結(jié)構(gòu)的數(shù)據(jù)表,目前只有 frm 和 ibd 文件,怎么樣得到 create table 命令?
根據(jù)底層數(shù)據(jù)存儲的理解,table 表結(jié)構(gòu)存儲在 frm 文件中,而目前已經(jīng)有相應(yīng)的方法從中提取出 create table 命令,
這樣就可以用于在新的 mysql 實(shí)例中建立 table 。
tablespace id 不對應(yīng)?
在第4步,嘗試導(dǎo)入數(shù)據(jù)的時(shí)候,
> ALTER TABLE km8.users625 IMPORT TABLESPACE; ERROR 1030 (HY000): Got error -1 from storage engine總是出現(xiàn)失敗,同時(shí)在 mysql 新實(shí)例的日志中發(fā)現(xiàn)這樣的錯(cuò)誤:
mysqld: InnoDB: Error: tablespace id in file './km8/users625.ibd' is 18446744073709551615, but in the InnoDB mysqld: InnoDB: data dictinary it is 1.原來在內(nèi)部,ibd 文件本身有一個(gè) id,必須和 mysql innodb 內(nèi)部的 table 元數(shù)據(jù)相對應(yīng),才可以進(jìn)行導(dǎo)入。
根據(jù)錯(cuò)誤信息搜索到一篇文章,其中提到兩種辦法:
users625 表,就可以對應(yīng) id,并進(jìn)行導(dǎo)入。
考慮第 1 種方法,要預(yù)先建立上億張空表?!這根本不可能。
于是嘗試第 2 種方法,研究 ibd 的文件格式,修改對應(yīng) id。
用二進(jìn)制編輯器打開 users625.ibd 文件,
18:26:08 UTC - mysqld got signal 6. This could be because you hit a bug. It is also possible that this binary or one of the libraries it was linked against is corrupt, improperly built or misconfigured. This error can also be cuased by malfunctioning hardware.不敢相信自己的眼睛,居然有錯(cuò)誤 log 在二進(jìn)制文件里?!ibd 的文件格式可沒有這么說明過。
隨便找一個(gè)鄰居表正常的 ibd 文件作對比,
看來是出現(xiàn)了 bug ,崩潰的環(huán)境直接將數(shù)據(jù)文件給毀了,這也解釋了為什么 tablespace id 會那么大,因?yàn)?log
覆蓋了原本的 id 字段,使 mysql 解讀出了一個(gè)好笑的數(shù)字。
暫時(shí)放棄
這種情況下,還沒有辦法將數(shù)據(jù)恢復(fù)回來,只能暫時(shí)將表刪除,新建空表,保證上層應(yīng)用程序可以運(yùn)行。
將 ibd 文件備份下來,看后續(xù)還沒有其它的辦法將其恢復(fù)。
檢測所有 table 狀態(tài)
當(dāng)前只發(fā)現(xiàn)一個(gè)出現(xiàn)問題的 table ,可能同時(shí)也有其它的 table 出現(xiàn)問題。對此需要做一個(gè)全面的檢測,
檢測有沒有其它的表受到牽連。
寫在最后
數(shù)據(jù)庫的備份是非常重要的!直接導(dǎo)入備份數(shù)據(jù),是解決問題最保險(xiǎn)最便捷的辦法。
如果沒有備份,遇到 bug 丟失數(shù)據(jù),只能怪時(shí)運(yùn)不濟(jì)。
同時(shí)數(shù)據(jù)庫也最好選擇穩(wěn)定的版本,降低出現(xiàn) bug 的概率。
轉(zhuǎn)載于:https://www.cnblogs.com/dreamanddead/p/recover-mysql-innodb-table-data-from-ibd-file.html
總結(jié)
以上是生活随笔為你收集整理的mysql innodb 从 ibd 文件恢复表数据的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 文件中的类都不能进行设计,因此未能为该文
- 下一篇: java.lang.IllegalAcc