直接添加唯一索引会因重复数据报错,需先查重清理再创建;ALTER TABLE ADD UNIQUE与CREATE UNIQUE INDEX效果相同;唯一索引允许多个NULL但存在语义陷阱;建索引会锁表,线上需谨慎评估。

直接添加唯一索引会报错:Duplicate entry
执行 CREATE UNIQUE INDEX 时如果字段已有重复值,MySQL 立即报错 Duplicate entry 'xxx' for key 'idx_name',不会继续。这不是语法问题,而是数据校验失败。
- 先用
SELECT column, COUNT(*) FROM table GROUP BY column HAVING COUNT(*) > 1找出重复项 - 清理或合并重复数据(比如保留最小
id的行,删其余) - 确认无重复后再建索引,否则操作中断
ALTER TABLE ADD UNIQUE 和 CREATE UNIQUE INDEX 效果一样
两者最终都生成同类型的约束,区别只在语法习惯和是否显式命名索引:
-
ALTER TABLE t ADD UNIQUE (col)—— MySQL 自动命名为col(若未指定) -
CREATE UNIQUE INDEX idx_col ON t(col)—— 可自定义索引名,便于后续DROP INDEX idx_col ON t - 对单列、多列、前缀长度(如
(col(10)))的支持完全一致
唯一索引允许 NULL,但有陷阱
MySQL 的唯一索引允许多个 NULL 值(标准 SQL 要求 NULL 不参与唯一性比较),这点常被误认为“失效”:
- 如果业务逻辑中把空字符串
''和NULL混用,可能漏掉重复校验 - 建议统一用
NOT NULL DEFAULT ''+ 唯一索引,避免 NULL 干扰 - 若字段必须允许空值,且需语义级唯一(即“空也算一个值”),得靠应用层或触发器兜底
建索引过程锁表,线上要谨慎
MySQL 5.6+ 支持 ALGORITHM=INPLACE,但并非所有情况都免锁:
- 加唯一索引属于 DDL,即使支持 INPLACE,仍会在最后阶段加短暂的排他元数据锁(MDL)
- 大表建议在低峰期执行,或使用
pt-online-schema-change工具规避长事务阻塞 - 建索引期间
SHOW PROCESSLIST里能看到状态为altering table,此时写入会等待










