業務變更需將自增 INT 主鍵改為 CHAR(18)(如雪花算法 ID),且表內已有數據不能重建。本文提供零停機、分步驟、可回滾的變更方案,並分析外鍵、觸發器、複制等依賴物件的處理要點。
SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE REFERENCED_TABLE_NAME='t';-- 1. 移除 AUTO_INCREMENT 屬性 ALTER TABLE `t` MODIFY `id` INT NOT NULL; -- 2. 刪除主鍵約束 ALTER TABLE `t` DROP PRIMARY KEY; -- 3. 修改欄位型別(INT -> CHAR(18)) ALTER TABLE `t` MODIFY `id` CHAR(18) NOT NULL; -- 4. 重新建立主鍵 ALTER TABLE `t` ADD PRIMARY KEY (`id`); -- 5. 更新應用層生成邏輯(雪花 ID / UUID 等),不再依賴自增。
pt-online-schema-change \
--alter "MODIFY id CHAR(18) NOT NULL, DROP PRIMARY KEY, ADD PRIMARY KEY (id)" \
--alter-foreign-keys-method=auto \
--max-load "Threads_running=100" \
--critical-load "Threads_running=200" \
--chunk-time 0.5 \
--pause-file /tmp/pt-osc-pause \
--execute \
D=db,t=t
⚠️ pt-osc 會建立觸發器、影子表、重命名表,步驟 3/5/7 需元數據鎖(MDL),需配合--max-load、--tries參數避免長事務阻塞。
-- 子表外鍵欄位同步修改
-- 1. 刪除外鍵
ALTER TABLE child DROP FOREIGN KEY fk_child_parent;
-- 2. 修改子表欄位型別
ALTER TABLE child MODIFY parent_id CHAR(18) NOT NULL;
-- 3. 重建外鍵(父表主鍵已為 CHAR(18))
ALTER TABLE child ADD CONSTRAINT fk_child_parent
FOREIGN KEY (parent_id) REFERENCES parent(id)
ON DELETE RESTRICT ON UPDATE CASCADE;
SELECT COUNT(*), MIN(id), MAX(id) FROM t;SHOW SLAVE STATUS\G 確認 Seconds_Behind_Master=0。RENAME TABLE t_new TO t_old, t_old TO t(pt-osc 保留舊表)或從備份恢復。| 坑點 | 後果 | 避坑 |
|---|---|---|
直接 MODIFY id CHAR(18) 不刪主鍵 | 報錯 ERROR 1025 或隱式轉換導致數據截斷 | 嚴格按順序:去自增→刪主鍵→改型別→加主鍵 |
| 外鍵未同步修改 | 子表插入報錯 Cannot add or update a child row | 先刪外鍵,同步改型別,再加外鍵 |
| 應用層仍傳 INT | 隱式轉換 '123' -> 123,主鍵衝突或查詢不到 | 同步發布應用代碼,統一用字符串 |
| binlog_format=STATEMENT | 主從數據不一致(型別轉換非確定性) | 變更期間臨時設 SET SESSION binlog_format=ROW |
主鍵型別變更是「心臟手術」,務必在測試環境全流程演練、量化鎖表時間、驗證應用兼容性,方可上生產。pt-osc 是大表的標準選擇,小表低峰直改更簡潔。