PostgreSQL中应显式创建SEQUENCE并用nextval()绑定列,而非SERIAL;MySQL 8.0+虽支持SEQUENCE但功能受限,宜用单行表或UUID/Snowflake替代;Oracle/SQL Server序列行为差异大,需注意CACHE、START WITH等配置;跨库ID生成应由应用层统一管控,避免依赖数据库序列自动同步。

PostgreSQL 里用 SEQUENCE 替代 SERIAL 的实际写法
直接删掉 SERIAL,它只是语法糖,底层就是 SEQUENCE + DEFAULT。真正可控、可跨库迁移的写法是显式创建序列并绑定到列。
CREATE SEQUENCE user_id_seq START WITH 1 INCREMENT BY 1;- 建表时用
DEFAULT nextval('user_id_seq'),不要用SERIAL - 如果已有数据,记得调用
SELECT setval('user_id_seq', (SELECT MAX(id) FROM users));同步当前最大值 - 注意:序列名在 PostgreSQL 中默认属于 public schema,跨 schema 引用需写成
schema_name.sequence_name
MySQL 8.0+ 没有原生 SEQUENCE,但可以模拟
MySQL 直到 8.0 才支持 SEQUENCE 对象(非标准 SQL,且功能受限),多数生产环境仍靠 AUTO_INCREMENT 或应用层生成。若硬要“跨库对齐”,得自己兜底。
- MySQL 8.0+ 可建:
CREATE SEQUENCE user_id_seq START WITH 1 INCREMENT BY 1;,但不支持OWNED BY,必须手动在INSERT里写NEXTVAL(user_id_seq) - 更稳妥的做法是:用一张单行表(如
seq_user_id)存当前值,配合UPDATE ... RETURNING(MySQL 8.0.29+)或SELECT ... FOR UPDATE+ 应用层递增 - 避免用
LAST_INSERT_ID()回填,它只对AUTO_INCREMENT列有效,和序列无关
Oracle 和 SQL Server 的序列对象差异要点
Oracle 的 SEQUENCE 是独立对象,SQL Server 的 SEQUENCE 也是,但两者默认行为不同,跨库时容易漏掉关键配置。
- Oracle 默认
NOCACHE,高并发下性能差;建议加CACHE 20,但要注意实例崩溃可能导致跳号 - SQL Server 的
SEQUENCE必须显式指定START WITH和INCREMENT BY,否则报错;且不支持OWNED BY,必须在INSERT或DEFAULT里调用NEXT VALUE FOR seq_name - Oracle 中
currval和nextval是会话级的,SQL Server 中CURRENT_VALUE是序列自身的当前值,无需会话上下文 - 所有数据库中,序列值一旦被
nextval消费就不可回退,哪怕事务回滚 —— 这点常被忽略,导致 ID 不连续却误以为出 bug
跨数据库统一 ID 生成的务实策略
真正在多个 DB 间切换或共存时,靠 DDL 对齐序列远远不够。核心矛盾不在语法,而在语义保障和运维习惯。
- 放弃“完全自动同步序列状态”的想法。不同数据库的序列持久化机制不同(如 MySQL 序列值存在 data dictionary,PostgreSQL 存在系统表,Oracle 在数据字典视图中),无法靠脚本一键对齐
- 应用层统一用 UUID v4 或雪花算法(Snowflake)生成 ID,数据库列改为
CHAR(36)或BIGINT,彻底绕开序列管理问题 - 如果必须用数字主键,至少把序列起始值设为大数(如
START WITH 1000000),给人工干预留余地;同时监控各库序列剩余可用范围(如SELECT last_value, max_value FROM pg_sequences) - 迁移旧数据时,别依赖目标库的序列自动增长 —— 先批量插入带 ID 的数据,再用
setval/ALTER SEQUENCE RESTART WITH/DBCC CHECKIDENT调整起点










