自增主键(AUTO_INCREMENT)是MySQL默认且最安全的主键选择,需满足索引约束、推荐BIGINT类型,并可通过CREATE或ALTER设置起始值;多序列需求需用sequence表+原子化nextval()函数实现;LAST_INSERT_ID()返回本会话最近插入值,SHOW TABLE STATUS显示元数据中“下一个值”,二者语义不同。

自增主键(AUTO_INCREMENT)是默认且最安全的选择
MySQL 没有原生 SEQUENCE 对象,AUTO_INCREMENT 就是事实标准。它由 InnoDB 引擎内部维护,线程安全、无需额外表或函数,适合绝大多数主键场景。
关键约束必须满足:自增列必须是索引的一部分(主键或唯一键),否则建表会报错 ERROR 1075;数据类型建议用 BIGINT,避免 INT 溢出(21亿上限)。
- 建表时指定起始值:
CREATE TABLE t (id BIGINT AUTO_INCREMENT PRIMARY KEY) AUTO_INCREMENT = 1000; - 运行中重设起点:
ALTER TABLE t AUTO_INCREMENT = 2000;—— 注意:该值必须严格大于当前最大id,否则无效 - 插入时不填自增列即可:
INSERT INTO t (name) VALUES ('foo');,MySQL 自动分配下一个值
需要多组独立序列时,用 sequence 表 + 函数模拟
当业务要求多个逻辑序列(如订单号、流水号、日志ID 分开计数),单张表的 AUTO_INCREMENT 不够用,就得自己建表模拟。
核心是三要素:一张 sequence 表、一个 nextval() 函数、事务隔离保证并发安全。
- 建表语句必须带
PRIMARY KEY(name),否则nextval的UPDATE可能锁全表 -
nextval()函数里不能只用SELECT + INSERT/UPDATE两步,必须合并在一条UPDATE里,否则高并发下会重复取值 - 示例函数逻辑:
UPDATE sequence SET current_value = current_value + increment WHERE name = 'order_seq'; SELECT current_value FROM sequence WHERE name = 'order_seq';
LAST_INSERT_ID() 和 SHOW TABLE STATUS 的区别必须分清
这两个常被混用,但语义完全不同,用错会导致逻辑错误。
-
LAST_INSERT_ID()返回**当前连接**最近一次INSERT生成的自增值,只对本会话有效,批量插入时只返回第一个 ID -
SHOW TABLE STATUS LIKE 't'查的是表元数据里的Auto_increment值,即“下一个将要分配的值”,但它不是实时快照 —— 如果其他连接刚插入了一行,这个值可能还没刷新,尤其在低频写入时误差明显 - 想查某张表当前最大 ID,老老实实
SELECT MAX(id) FROM t更可靠(注意加索引)
重置 AUTO_INCREMENT 要避开并发写入窗口
用 ALTER TABLE t AUTO_INCREMENT = N 重置时,如果表正在被频繁写入,N 可能瞬间失效,甚至导致后续插入失败。
- 真正安全的做法是先停写(或切到维护窗口),再执行
ALTER - 不要用“删列重建”这种操作:
ALTER TABLE t DROP id; ALTER TABLE t ADD id ...—— 这会锁表、丢数据、破坏外键,且无法保证新 ID 连续 - 如果只是想清理间隙(比如删了大量中间数据),别折腾自增计数器,间隙本身不影响功能,强行重排反而引发风险
nextval() 函数在高并发下的原子性保障 —— 它依赖 InnoDB 的行级锁和事务隔离级别,一旦函数里漏掉 COMMIT 或用了非事务引擎(如 MyISAM),就会出现重复值。


















