表 user 無唯一約束,name 列出現重複(含大小寫差異),需去重並加唯一索引。直接 ALTER TABLE ADD UNIQUE 會報錯。
CREATE TABLE `user` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
`name` CHAR(10) NOT NULL DEFAULT '',
`extra` CHAR(10) NOT NULL DEFAULT ''
);
-- 數據含重複:user3、user2、USER2、user6、USER6(大小寫視為不同值)
SELECT * INTO OUTFILE '/tmp/user.txt' FROM `user`;
TRUNCATE TABLE `user`;
ALTER TABLE `user` MODIFY `name` CHAR(10) BINARY NOT NULL DEFAULT '';
ALTER TABLE `user` ADD UNIQUE KEY (`name`);
BINARY 使 CHAR 按二進制比較,user2 ≠ USER2。
-- 策略 A:新數據覆蓋舊數據(保留最新記錄)
LOAD DATA INFILE '/tmp/user.txt' REPLACE INTO TABLE `user`;
-- 結果:刪除 2 條重複,保留 id=8(user2)、id=6(user3) 等後寫入記錄
-- 策略 B:跳過新數據(保留最舊記錄)
LOAD DATA INFILE '/tmp/user.txt' IGNORE INTO TABLE `user`;
-- 結果:跳過 2 條重複,保留 id=2(user2)、id=3(user3) 等首寫入記錄
REPLACE:唯一鍵衝突時刪除舊行 + 插入新行(自增 ID 會變)。IGNORE:唯一鍵衝突時忽略新行,保留舊行。BINARY 屬性對大小寫敏感去重至關重要。mysqld 進程用戶可寫,目標文件不可存在(安全限制)。TRUNCATE 瞬時完成,LOAD DATA 速度極快。
-- 創建新表結構
CREATE TABLE `user_new` LIKE `user`;
ALTER TABLE `user_new` MODIFY `name` CHAR(10) BINARY NOT NULL DEFAULT '';
ALTER TABLE `user_new` ADD UNIQUE KEY (`name`);
-- 去重寫入(保留最舊)
INSERT IGNORE INTO `user_new` SELECT * FROM `user`;
-- 原子切換
RENAME TABLE `user` TO `user_old`, `user_new` TO `user`;
適合無法承受寫入停機的場景,需處理切換期間增量同步(觸發器/應用雙寫/CDC)。