【1】故障模擬准備環境
這里以innodb為例
【1.1】配置參數
開啟獨立表空間 innodb_file_per_table;
【1.2】構建測試數據
create database test; create table a(id int,num int); insert into a values(1,11),(2,12);
【2】故障模擬
【2.1】在業務正在運行的情況下,手動刪除 test庫 下的 a.frm
【2.2】刪除完之后,會發生什么?
在沒有執行drop table的時候,還是可以查詢表,查看表結構的,執行后,就查不到了。
如上圖所示可知(在業務還在跑的情況下):
無論是對於數據表的增刪查改,還是數據結構的增刪查改。統統失效,連 information_schema.columns 都查不到(是因為執行了drop table,雖然報錯了,但是把數據字典系統表里的相關信息還是刪除了)。
【3】如何徹底刪除這個表
【3.1】保留這個表數據(要是真不想要了,這步也可以不用做)
cp a.ibd a_bak.ibd
【3.2】隨便找個其他表的frm文件重命名成故障表的frm文件
cp test1.frm a.frm
【3.3】加上權限,如下圖可以發現是root創建的
chown -R mysql:mysql /data/mysql
【3.4】查看表與表結構,然后刪除表
我們可以發現已經有了,但很明顯,表結構不是我們a表的結構,而是test1表結構。弄好了之后,發現我們可以刪除表了!
【3.5】如果用了其他表的表結構替換會發生什么?
對B表進行了同樣的操作;B表與A表代碼一樣。
用test1表的frm 覆蓋並重命名成 b表的frm之后,查詢b表居然顯示的是 test1表的數據!!
b.frm 加上之后,刪除表后 ,這個名稱就可以重建了。
【4】恢復使用
故障前提,操作完【1】【2】
【4.1】直接在test1庫恢復a表
(0)去test1庫構建相同名稱表
use test1;
create table a(id int,num int);
如何獲取表結構?只能desc,information_schem,binlog里看看有沒有,最靠譜的當然是去備份里找。
直接在test1庫恢復a表。
(1)備份frm,把我們原始的 失去frm 對應idb的文件拷貝過來
(2)釋放表空間
alter table a discard tablespace;
如下圖所示,釋放表空間,只是把idb數據清空了,frm表結構文件還在。
(3)把我們要恢復的ibd文件,重命名成a.ibd
一定要記得,權限問題;
(4)重新導入表空間
alter table a import tablespace;
至此搞定;
【4.2】在原庫恢復
故障前提,操作完【1】【2】
(1)備份
cp -r a.ibd a_bak.ibd
(2)隨便找個表frm 復制重命名成 a.frm,刪除表
復制前,刪除表
cp -r test1.frm a.frm
chown -R mysql:mysql /data/mysql
復制后,刪除表
(3)重建表結構相同的a表
create table a(id int,num int);
-- 如何獲取表結構? 備份、主從、binlog......
(4)銷毀表空間
alter table a discard tablespace;
(5)復制備份文件成a.ibd,導入表空間
alter table a import tablespace;
成功!
思考1:可否直接替換ibd?
我建完一個同表結構新的空表之后,可不可以直接用我們需要恢復的ibd文件,替換這個ibd文件呢?
我們初始化,重新新建一個空白的a表;
(1)重建表:create table a(id int,num int);
(2)覆蓋文件
(3)查看是否有數據,並沒有,直接覆蓋失敗
結論:不可以;
思考2:沒建表的情況下,可以直接用新建的frm和要恢復的ibd使用表空間導入嘛?
不可以,會報錯表不存在。而后,即使你新建表也會報錯。
如果需要新建,這個時候需要drop table a; 之后,才能夠再次新建。