结论先行:
✅ 可以------在没有显式主键的情况下,InnoDB 会优先选择第一个 NOT NULL 的唯一索引作为"聚簇索引(主键)"。
❌ 但不能直接把一个普通唯一索引"变成"主键,需要符合规则。
下面详细说明 👇
一、InnoDB 如何选择主键(非常重要)
InnoDB 的主键本质是 聚簇索引(Clustered Index)。
如果表中 没有定义 PRIMARY KEY,InnoDB 会按以下顺序选择:
✅ 选择顺序
- 显式定义的 PRIMARY KEY
- 第一个 NOT NULL 的唯一索引
- 系统自动生成的隐藏 ROW_ID(6 字节)
📌 唯一索引 ≠ 一定是主键
📌 只有 NOT NULL 的唯一索引才可能成为主键
二、示例说明
✅ 情况 1:唯一索引可充当主键
CREATE TABLE user (
email VARCHAR(100) NOT NULL,
UNIQUE KEY uk_email (email)
);
👉 InnoDB 会:
• 使用 uk_email 作为 聚簇索引
• 等价于主键(但不叫 PRIMARY KEY)
SHOW INDEX FROM user;
你会看到:
• Key_name = uk_email
• Non_unique = 0
• 实际承担主键角色
❌ 情况 2:唯一索引允许 NULL → 不能做主键
CREATE TABLE user (
email VARCHAR(100),
UNIQUE KEY uk_email (email)
);
❌ 因为允许 NULL
❌ InnoDB 不会用它作为主键
✅ 会使用隐藏 ROW_ID
三、能不能"把唯一索引改为主键"?
✅ 正确做法
ALTER TABLE user
ADD PRIMARY KEY (email);
⚠️ 前提条件:
• email 必须是 NOT NULL
• 不能有重复值
❌ 错误理解
-- 这并不会让 uk_email 成为主键
ALTER TABLE user ADD UNIQUE KEY uk_email (email);
👉 它只是唯一索引,不是 PRIMARY KEY。
四、唯一索引"充当主键"的优缺点
✅ 优点
• 省去一个额外的自增 ID
• 减少一次索引查找(覆盖索引更友好)
• 适合 业务主键明确 的场景
❌ 缺点
• 主键更新成本高(InnoDB 会移动行)
• 业务字段变更会影响所有二级索引
• UUID / 字符串做主键会导致页分裂严重
五、强烈推荐的通用设计 ✅
场景 推荐方案
绝大多数业务表 id BIGINT AUTO_INCREMENT PRIMARY KEY
业务唯一字段 UNIQUE KEY uk_xxx
高并发写入 自增 / 雪花 ID 主键
读多写少 可考虑业务唯一字段做主键
六、一句话总结
没有主键时,InnoDB 会用第一个 NOT NULL 的唯一索引当作主键;但它仍然是唯一索引,不是 PRIMARY KEY。