生產環境偶發操作失誤直接 rm -rf 刪除了 .frm 和 .ibd 文件,導致表在數據字典中仍存在但物理文件丟失,出現「創建報錯 Table already exists、刪除報錯 Unknown table」的詭異狀態。本文提供不依賴全量備份、僅恢復表結構可用的應急方案。
適用條件:
1. 僅需恢復表結構(數據不可恢復,除非配合 extundelete 磁盤級恢復)
2. 無全量備份可用
3. 同理適用於單表遷移場景(DISCARD/IMPORT 速度遠快於 dump/load)
# 直接刪除物理文件 rm -rf tracking20160501.* # MySQL 客戶端表現 mysql> SHOW TABLES; -- 表不見了 mysql> CREATE TABLE tracking20160501(id int); ERROR 1050 (42S01): Table 'tracking20160501' already exists mysql> DROP TABLE tracking20160501; ERROR 1051 (42S02): Unknown table 'kdnet_analyze.tracking20160501' # 文件系統層面 ls tracking20160501.* tracking20160501.ibd -- CREATE 嘗試導致 MySQL 重新創建了空 ibd
核心原因:InnoDB 數據字典與文件系統不同步。MySQL 內部數據字典仍記錄該表元數據,但物理文件已不存在,導致 DDL 操作進入死循環。
核心思路:找一個結構相同的表,複製其 .frm 和 .ibd 文件重命名,配合 DISCARD TABLESPACE / IMPORT TABLESPACE 重新註冊表空間。
cp -a ip_taobao.frm tracking20160501.frm
必須使用 -a 保持所有者/權限一致,避免 MySQL 讀取失敗。ALTER TABLE tracking20160501 DISCARD TABLESPACE;
若報錯嘗試重啟 MySQL 服務後再試。
cp -a ip_taobao.ibd tracking20160501.ibd
ALTER TABLE tracking20160501 IMPORT TABLESPACE;
大表導入耗時較長(示例 7 分半),耐心等待,觀察錯誤日誌確認無腐壞報警。
SELECT * FROM tracking20160501 LIMIT 1; DROP TABLE tracking20160501; CREATE TABLE tracking20160501(id int); -- 應可正常執行
mysqldump -d db_name > schema.sql 納入每日備份策略此方案利用 InnoDB 可傳輸表空間特性,以「借殼」方式重建表與表空間映射關係,是無備份情況下恢復表可用性的最快路徑。但需明確:數據已不可逆丟失,核心價值在於釋放表名、恢復 DDL 操作能力。