萬盛學電腦網

您现在的位置: 萬盛學電腦網 >> 程式設計 >  >> 資料庫 >> MySQL 教學

從 frm/ibd 檔案救回 MySQL InnoDB 資料:ibdata 損壞/遺失完整教學

適用場景與前提

  • 僅適用於 InnoDB 引擎;MyISAM 只需複製 .MYD/.MYI/.frm 即可。
  • 必須啟用 innodb_file_per_table=1(獨立表空間),否則無法單表恢復。
  • 擁有目標表的 .frm(結構)與 .ibd(資料/索引)檔案。

第一階段:恢復表結構

  1. 建立乾淨資料庫與同名空表(引擎必須為 InnoDB):
    CREATE DATABASE recover_db;
    USE recover_db;
    CREATE TABLE `target_table` (`id` BIGINT(20)) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    
  2. 停止 MySQL,用備份的 .frm 覆蓋新建的 .frm。
  3. 修改 my.cnf 加入 innodb_force_recovery=1(若失敗嘗試 2~6),啟動 MySQL。
  4. 執行 SHOW CREATE TABLE target_table; 取得完整建表 SQL。
  5. 關閉 MySQL,註釋掉 innodb_force_recovery,重新啟動。

第二階段:恢復資料(核心:對齊 Tablespace ID)

  1. 用上一步取得的 SQL 在新資料庫建立正式表結構。
  2. 執行 ALTER TABLE target_table DISCARD TABLESPACE; 丟棄新表的 .ibd,使 .frm 與 .ibd 分離。
  3. 將備份的 .ibd 複製到資料目錄下。
  4. 執行 ALTER TABLE target_table IMPORT TABLESPACE; 會報錯:
    ERROR 1030 (HY000): Got error -1 from storage engine
    InnoDB: Error: tablespace id in file './target_table.ibd' is 112,
    but in the InnoDB data dictionary it is 1.
    

    舊表 Tablespace ID=112,新表僅建立一次 ID=1。

  5. 建立 111 個臨時表將 ID 遞增至 112:
    DELIMITER //
    CREATE PROCEDURE inc_tablespace()
    BEGIN
      DECLARE i INT DEFAULT 1;
      WHILE i <= 111 DO
        SET @s = CONCAT('CREATE TABLE tmp_', i, ' (id INT) ENGINE=InnoDB');
        PREPARE stmt FROM @s; EXECUTE stmt; DEALLOCATE PREPARE stmt;
        SET i = i + 1;
      END WHILE;
    END//
    DELIMITER ;
    CALL inc_tablespace();
    DROP PROCEDURE inc_tablespace;
    
  6. 再次 DISCARD TABLESPACE、複製原 .ibd、IMPORT TABLESPACE,此次應成功。
  7. 若查詢仍無資料,重新啟用 innodb_force_recovery=1~6 直到可讀取,隨即 mysqldump 導出。
  8. 在全新資料庫匯入導出的 SQL,完成遷移。

批量處理分表腳本範例

for i in $(seq 0 111); do
  mysql -uroot -P3306 -h127.0.0.1 -Drecover_db \
    -e "CREATE TABLE shard_$i (id BIGINT(20) PRIMARY KEY) ENGINE=InnoDB";
done

for i in $(seq 0 111); do
  mysql -uroot -P3306 -h127.0.0.1 -Drecover_db \
    -e "ALTER TABLE shard_$i DISCARD TABLESPACE";
done

# 複製備份的 .ibd 至 recover_db 目錄(注意檔案權限 chown mysql:mysql)

for i in $(seq 0 111); do
  mysql -uroot -P3306 -h127.0.0.1 -Drecover_db \
    -e "ALTER TABLE shard_$i IMPORT TABLESPACE";
done
copyright © 萬盛學電腦網 all rights reserved