萬盛學電腦網

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

MySQL 大表新增欄位安全策略:影子表法、主從切換與線上變更工具

問題背景

MySQL 執行 ALTER TABLE ... ADD COLUMN 會鎖表(5.6+ InnoDB 支援 Online DDL 但仍有鎖定風險),大表操作可能導致:

  • 長時間鎖表阻塞讀寫
  • 主從延遲甚至從庫卡住
  • 服務不可用、甚至崩潰

方案一:影子表法(通用、無需工具)

-- 1. 建立新表複製結構(含索引)
CREATE TABLE new_table LIKE old_table;

-- 2. 新表新增欄位
ALTER TABLE new_table ADD COLUMN new_col VARCHAR(255) DEFAULT '' COMMENT '新欄位' AFTER id;

-- 3. 複製資料(可分批次)
INSERT INTO new_table (col1, col2, ...) SELECT col1, col2, ... FROM old_table;

-- 4. 增量同步(若有建立時間欄位)
-- 記錄開始複製時間點 T1
INSERT INTO new_table (col1, col2, ...) 
SELECT col1, col2, ... FROM old_table WHERE create_time > 'T1';

-- 5. 低峰期切換
RENAME TABLE old_table TO old_table_bak, new_table TO old_table;

風險:切換瞬間極少量新寫入可能丟失,極高一致性要求建議停機窗口操作。

方案二:主從切換(零停機)

  1. 在從庫執行 ALTER TABLE 加欄位
  2. 等待從庫同步完成
  3. 主從切換(提升從庫為主)
  4. 原主庫同步新結構後掛回為從

前提:主從架構健全、切換工具成熟(MHA、Orchestrator)。

方案三:線上變更工具

  • pt-online-schema-change (Percona Toolkit):觸發器+影子表,支援暫停/限流
  • gh-ost (GitHub):無觸發器、基於 Binlog 同步、可測試模式
  • OSC (Facebook):類似原理
# pt-osc 範例
pt-online-schema-change --alter "ADD COLUMN new_col VARCHAR(255)" \
  D=db,t=old_table --execute --max-load Threads_running=50 --critical-load Threads_running=100

經驗法則

資料量建議策略
< 10 萬行直接 ALTER TABLE 通常秒級完成
10 萬 - 1000 萬影子表法或 pt-osc,低峰期操作
> 1000 萬gh-ost 或主從切換,嚴格監控
極高一致性要求停機維護窗口

最佳實踐檢查清單

  • ✅ 先在測試/預發環境驗證
  • ✅ 確認磁碟空間充足(影子表需雙倍空間)
  • ✅ 備份原表(mysqldump 或快照)
  • ✅ 監控 Threads_running、主從延遲、磁碟 I/O
  • ✅ 準備回滾方案(保留舊表一段時間)
  • ✅ 通知相關方(開發、運維、業務)
copyright © 萬盛學電腦網 all rights reserved