MySQL 5.6不支持SEQUENCE对象,正确答案是a(不支持);其仅通过AUTO_INCREMENT实现类似功能,且该功能需依附于索引列,官方直到8.0版本才引入原生序列支持。

MySQL 不支持序列对象,别被名字误导
MySQL 没有 SEQUENCE 对象(像 PostgreSQL 或 Oracle 那样),所谓“用序列实现非主键自增”在 MySQL 里根本不存在。试图执行 CREATE SEQUENCE 会直接报错 ERROR 1064 (42000)。所有声称“MySQL 支持序列”的说法,要么混淆了版本(MySQL 8.0+ 仍无原生序列),要么指代用户变量或模拟逻辑——本质还是靠触发器或应用层控制。
AUTO_INCREMENT 必须依附于键,但不强制是主键
MySQL 允许非主键列带 AUTO_INCREMENT,前提是它必须是 KEY(普通索引、唯一索引均可)。常见错误是只加 AUTO_INCREMENT 却漏建索引:
-
ALTER TABLE users ADD COLUMN seq_no INT AUTO_INCREMENT;→ 报错:「Incorrect table definition; there can be only one auto column and it must be defined as a key」 - 正确写法必须包含索引声明:
ALTER TABLE users ADD COLUMN seq_no INT AUTO_INCREMENT UNIQUE;或ADD COLUMN seq_no INT AUTO_INCREMENT, ADD KEY(seq_no);
注意:即使加了 UNIQUE,该列也不能同时设为 NULL;NOT NULL 是隐式强制的。
触发器是实际可用的通用方案,但并发时要小心
用触发器模拟自增最灵活,也兼容所有 MySQL 版本。核心逻辑是:插入前查当前最大值,+1 后赋给新行。但以下细节极易出错:
面向 CRM 系统的 MySQL 8 数据库模式设计。当用户需要为客户关系管理(CRM)系统设计、评审、优化或生成数据库模式时,应使用此项技能。
- 不能用
SELECT MAX(col) FROM tbl直接赋值——若表为空,结果为NULL,NULL + 1还是NULL,导致插入失败;必须用COALESCE(MAX(col), 0)或IFNULL(MAX(col), 0) - 没加
ORDER BY或显式锁,在高并发下可能查到相同最大值,造成重复值(如两个事务同时读到 100,都写 101) - 触发器中不能对本表做
SELECT ... FROM tbl(MySQL 5.7+ 会报错「Can't update table 'tbl' in stored function/trigger」),需改用变量或子查询嵌套
安全写法示例:
DELIMITER // CREATE TRIGGER tr_users_before_insert BEFORE INSERT ON users FOR EACH ROW BEGIN DECLARE next_val INT DEFAULT 0; SELECT COALESCE(MAX(seq_no), 0) + 1 INTO next_val FROM users; SET NEW.seq_no = next_val; END// DELIMITER ;
真正容易被忽略的点:自增值不回滚、不重用、不保证全局顺序
哪怕用了触发器,也要清楚这三件事:
- 事务回滚后,已分配的自增值不会回收——下一次插入仍是递进的,中间可能出现“空洞”
- 如果某次插入因约束失败而中断,该次生成的值也不会被后续复用
- 没有全局锁保护时,多个并发插入可能产生非严格时间顺序的值(比如先提交的事务反而拿到更小的
seq_no)
所以,如果你需要的是“严格按插入时间递增且无空洞”的序号,MySQL 原生机制做不到——得靠应用层用 Redis 自增或预分配段号来兜底。










