利用 information_schema.TABLES 查詢所有 MyISAM 表,生成 ALTER TABLE ... ENGINE=InnoDB 語句,寫入臨時檔再 SOURCE 執行。
-- 1. 清理舊臨時檔
\! rm -f /tmp/alter_innodb.sql
-- 2. 生成 ALTER 語句
SELECT CONCAT('ALTER TABLE `', TABLE_SCHEMA, '`.`', TABLE_NAME, '` ENGINE=InnoDB;')
FROM information_schema.TABLES
WHERE ENGINE = 'MyISAM'
AND TABLE_SCHEMA NOT IN ('mysql', 'information_schema', 'performance_schema', 'sys')
INTO OUTFILE '/tmp/alter_innodb.sql';
-- 3. 執行轉換
SOURCE /tmp/alter_innodb.sql;
-- 4. 清理臨時檔
\! rm -f /tmp/alter_innodb.sql
mysql -u root -p < convert_myisam_to_innodb.sql
mysql> \! rm -f /tmp/alter_innodb.sql
mysql> SELECT CONCAT('ALTER TABLE `', TABLE_SCHEMA, '`.`', TABLE_NAME, '` ENGINE=InnoDB;')
-> FROM information_schema.TABLES
-> WHERE ENGINE='MyISAM'
-> AND TABLE_SCHEMA NOT IN ('mysql','information_schema','performance_schema','sys')
-> INTO OUTFILE '/tmp/alter_innodb.sql';
mysql> SOURCE /tmp/alter_innodb.sql;
mysql> \! rm -f /tmp/alter_innodb.sql
-- 僅轉換資料量 < 100MB 的表
SELECT CONCAT('ALTER TABLE `', TABLE_SCHEMA, '`.`', TABLE_NAME, '` ENGINE=InnoDB;')
FROM information_schema.TABLES
WHERE ENGINE='MyISAM'
AND TABLE_SCHEMA NOT IN ('mysql','information_schema','performance_schema','sys')
AND (DATA_LENGTH + INDEX_LENGTH) < 100*1024*1024
INTO OUTFILE '/tmp/alter_small.sql';
SOURCE /tmp/alter_small.sql;
-- 大表使用 pt-online-schema-change (Percona Toolkit)
-- pt-online-schema-change --alter "ENGINE=InnoDB" D=db,t=big_table --execute
-- 檢查剩餘 MyISAM 表
SELECT TABLE_SCHEMA, TABLE_NAME, ENGINE, DATA_LENGTH, INDEX_LENGTH
FROM information_schema.TABLES
WHERE ENGINE='MyISAM'
AND TABLE_SCHEMA NOT IN ('mysql','information_schema','performance_schema','sys');
-- 檢查表狀態
SHOW TABLE STATUS WHERE Engine='InnoDB' \G
ALTER TABLE ... ENGINE=InnoDB 會全表鎖定,大表可能耗時數小時# 無鎖線上轉換
pt-online-schema-change \
--alter "ENGINE=InnoDB" \
D=your_db,t=your_table \
--user=root --password=xxx \
--max-load Threads_running=50 \
--critical-load Threads_running=100 \
--execute
原理:建立新表 → 建觸發器同步增量 → 複製歷史資料 → 交換表名 → 清理。