mysql存儲(chǔ)在磁盤中,各種天災(zāi)人禍都會(huì)導(dǎo)致數(shù)據(jù)丟失。大公司的時(shí)候我們常常需要做好數(shù)據(jù)冷熱備,對(duì)于小公司來(lái)說(shuō)要做好所有數(shù)據(jù)備份需要支出大量的成本,很多公司也是不現(xiàn)實(shí)的。萬(wàn)一還沒(méi)有做好備份,數(shù)據(jù)被誤刪除了,或者ibdata損壞了怎么辦呢?別擔(dān)心,只要有部分的frm、ibd存在就可以恢復(fù)部分?jǐn)?shù)據(jù)。
今天向大家分享下mysql通過(guò).frm和.ibd文件恢復(fù)數(shù)據(jù)的方法,因?yàn)橹半娔X換系統(tǒng)的原因,忘記備份數(shù)據(jù)庫(kù),最后只能通過(guò)恢復(fù)工具找到數(shù)據(jù)庫(kù)的.frm和.ibd文件,為了恢復(fù)數(shù)據(jù),今天踩了不少坑,下面把我成功恢復(fù)的過(guò)程分享給大家;
整個(gè)恢復(fù)過(guò)程其實(shí)可以總結(jié)為下面幾步:
(1):恢復(fù)表結(jié)構(gòu)
(2):復(fù)制出來(lái)創(chuàng)建表的sql語(yǔ)句
(3):恢復(fù)表數(shù)據(jù)(在恢復(fù)表數(shù)據(jù)的時(shí)候,首先需要解除當(dāng)前創(chuàng)建的表與默認(rèn)生成的.ibd文件間的關(guān)系,接著將要恢復(fù)數(shù)據(jù)表的.ibd文件與當(dāng)前創(chuàng)建的表聯(lián)系起來(lái)即可)
做法步驟1--將原先的.ibd文件與原先的.frm文件解除綁定 做法步驟2--停掉服務(wù),新的.ibd文件覆蓋舊的.ibd文件,再開(kāi)啟服務(wù) 做法步驟3--將新的.ibd文件與.frm文件發(fā)生聯(lián)系
.frm文件:保存了每個(gè)表的元數(shù)據(jù),包括表結(jié)構(gòu)的定義等;
.ibd文件:InnoDB引擎開(kāi)啟了獨(dú)立表空間(my.ini中配置innodb_file_per_table = 1)產(chǎn)生的存放該表的數(shù)據(jù)和索引的文件。
1、安裝相同版本的mysql;
2、找回表結(jié)構(gòu)(若有表結(jié)構(gòu),直接導(dǎo)入表即可)
建立同名的表(InnoDB),不知道列數(shù)的話隨意一個(gè)字段即可(如果字段個(gè)數(shù)不一致會(huì)報(bào)錯(cuò),去日志文件中查看有列數(shù)重復(fù)這些步驟)
關(guān)閉mysql服務(wù)
用需要恢復(fù)的.frm文件覆蓋新生成的.frm文件。
修改my.ini配置innodb_force_recovery = 6進(jìn)入恢復(fù)模式(只讀)。
啟動(dòng)mysql服務(wù)。
desc tble_name或者show create table tbl_name獲取創(chuàng)建表結(jié)構(gòu)語(yǔ)句。(直接查看表設(shè)計(jì)字段會(huì)導(dǎo)致數(shù)據(jù)庫(kù)異常)
復(fù)制建表sql,刪除表(不能直接刪.frm和.ibd會(huì)導(dǎo)致新建時(shí)報(bào)已存在,如果直接刪除文件,需要將frm文件拷貝回來(lái),再drop表),執(zhí)行sql創(chuàng)建表結(jié)構(gòu)。(這個(gè)步驟要把innodb_force_recovery = 6注解掉或者回復(fù)為0,不然提示只讀)。
這里會(huì)出現(xiàn)啟動(dòng)后沒(méi)有表結(jié)構(gòu),這是需要查看mysql的日志文件
找到日志文件位置:
show variables like '%error%'
這里的.是相對(duì)于mysql的,windows可以根據(jù)快捷方式找到mysql位置然后再找.err錯(cuò)誤文件
找到報(bào)錯(cuò)信息為
2018-12-18T08:52:30.314230Z 2 [Warning] InnoDB: Table bookkeeping/concategory contains 1 user defined columns in InnoDB, but 3 columns in MySQL.
意思是新建的有1列,但是復(fù)制過(guò)來(lái)的frm文件中含有3列。這時(shí)候知道列數(shù),重做上述步驟。
單個(gè)執(zhí)行刪除表空間語(yǔ)句
ALTER TABLE <table_name> DISCARD TABLESPACE;
批量刪除空間,執(zhí)行以下語(yǔ)句。
SELECT CONCAT('ALTER TABLE ', table_name, ' DISCARD TABLESPACE;') FROM information_schema.TABLES WHERE TABLE_SCHEMA = 'db_name';
獲得每個(gè)表的刪除表空間語(yǔ)句,直接全部選中復(fù)制(Navicat)
在前后加上外鍵約束檢查關(guān)閉和開(kāi)啟執(zhí)行
2.將待恢復(fù)的<table_name>.ibd文件copy到目標(biāo)數(shù)據(jù)庫(kù)文件夾下(這時(shí)候在navicat中看不到表名,不要慌?。?!),并修改文件權(quán)限(chown u:g file),批量修改權(quán)限chown mysql:mysql /usr/mysql/data/db_name/*
單個(gè)執(zhí)行導(dǎo)入表空間語(yǔ)句
ALTER TABLE <table_name> IMPORT TABLESPACE;
批量導(dǎo)入表空間
SELECT CONCAT('ALTER TABLE ', table_name, ' IMPORT TABLESPACE;') FROM information_schema.TABLES WHERE TABLE_SCHEMA = 'db_name';
這里和刪除一樣,不贅述,復(fù)制所選語(yǔ)句,加上關(guān)閉開(kāi)啟檢查,執(zhí)行
1.mysql 1808錯(cuò)誤:這是由于mysql 5.6的文件恢復(fù)到mysql 5.7版本導(dǎo)致的錯(cuò)誤,需要在建表語(yǔ)句后面添加ROW_FORMAT=COMPACT
2.mysql 1812錯(cuò)誤:copy的ibd文件沒(méi)有賦權(quán),用chown u:g file
3.mysql 1451錯(cuò)誤: Cannot delete or update a parent row: a foreign
在前后加上
SET foreign_key_checks = 0; -- 先設(shè)置外鍵約束檢查關(guān)閉SET foreign_key_checks = 1; -- 開(kāi)啟外鍵約束檢查,以保持表結(jié)構(gòu)完整性
1.建立表結(jié)構(gòu)(有備份直接用,跳過(guò)第一步的找回表結(jié)構(gòu))
2.刪除新建的表空間
3.拷貝.ibd數(shù)據(jù)文件覆蓋新建的文件
4.導(dǎo)入表空間
如對(duì)本文有疑問(wèn),請(qǐng)?zhí)峤坏浇涣髡搲?,廣大熱心網(wǎng)友會(huì)為你解答!! 點(diǎn)擊進(jìn)入論壇