複製資料庫目錄到另一台機器,發現部分表僅有 .frm 檔案,啟動 MySQL 即報錯 "Table doesn't exist"。根因在於儲存引擎決定了檔案結構。
| 引擎 | .frm | .MYD | .MYI | 系統表空間 | 說明 |
|---|---|---|---|---|---|
| MyISAM | 表結構定義 | 資料檔案 | 索引檔案 | 無 | 三檔分離,可直接複製遷移 |
| InnoDB (file_per_table=OFF) | 表結構定義 | 無 | 無 | ibdata1/ibdata2... | 資料與索引混存於共享表空間,不可單表複製 |
| InnoDB (file_per_table=ON) | 表結構定義 | 無 | 無 | .ibd (獨立表空間) | 每表獨立 .ibd,可攜帶性較好,仍需配合表空間匯入 |
innodb_file_per_table=ON,但歷史版本或手動關閉時,所有 InnoDB 表資料寫入 ibdata1。.frm 僅存結構定義(列、型別、索引定義),不含任何資料與索引頁面。.frm 缺少對應的表空間檔案,引擎找不到資料頁 → 報錯。-- SQL 方式
ALTER TABLE `db`.`table` ENGINE=MyISAM;
-- phpMyAdmin:操作 → 表選項 → Storage Engine → MyISAM → 執行
轉換後會產生 .MYD/.MYI,可直接複製目錄遷移。但會失去事務、行鎖、外鍵、崩潰恢復等 InnoDB 核心特性。
# 1. 修改配置
[mysqld]
innodb_file_per_table=1
# 重啟生效
# 2. 重建表(觸發遷移至獨立 .ibd)
ALTER TABLE `db`.`table` ENGINE=InnoDB;
# 或
OPTIMIZE TABLE `db`.`table`;
重建後會產生 table.ibd,未來遷移可使用 Transportable Tablespace(FLUSH TABLES ... FOR EXPORT / IMPORT TABLESPACE)標準化流程。
# 來源端
mysqldump --single-transaction --master-data=2 -u root -p db table > table.sql
# 目標端
mysql -u root -p db < table.sql
跨版本、跨引擎、跨架構通用;大表配合pv顯示進度,或使用mydumper/myloader多執行緒加速。
SHOW TABLE STATUS FROM `db` LIKE 'table'\G
# Engine: InnoDB
# Row_format: Dynamic
# Data_length: 12345678
# Index_length: 8765432
# Comment:
# 檔案系統層面
ls -lh /var/lib/mysql/db/table.*
# -rw-r----- 1 mysql mysql 8.5K Jan 1 12:00 table.frm
# -rw-r----- 1 mysql mysql 112M Jan 1 12:05 table.ibd # file_per_table=ON 時出現
.frm 到新實例 → ERROR 1146 (42S02): Table doesn't exist。ibdata1 但未複製 ib_logfile* → 啟動崩潰恢復失敗。mysqldump / XtraBackup / Transportable Tablespace 三大標準遷移路徑。innodb_file_per_table=ON,便於後續管理與遷移。檔案層面的認知是 DBA 進階的分水嶺:懂得引擎如何組織資料,才能在遷移、備份、災難恢復時游刃有餘。