← 返回题目列表

Oracle 序列 Sequence 是什么?和自增主键有什么关系?

高频 简单 第 2 / 32 题 更新于 2026/07/28
OracleSequence自增主键Identity主键设计

简化版

Oracle Sequence 是独立的序列对象,用来生成递增或按规则变化的数字,常用于主键。传统 Oracle 常用 sequence.nextval 生成 ID;较新版本也支持 identity column。Sequence 生成的值不保证连续,因为缓存、回滚、并发、实例故障都可能产生跳号,但它能保证按序列规则生成唯一值。

详细版

Sequence 常见用法:

CREATE SEQUENCE user_seq START WITH 1 INCREMENT BY 1 CACHE 20;

INSERT INTO users(id, name)
VALUES (user_seq.NEXTVAL, 'Tom');

关键点:

  • NEXTVAL 获取下一个序列值;
  • CURRVAL 获取当前会话已取过的序列值;
  • CACHE 可以提升性能,但可能导致故障后跳号;
  • 事务回滚不会回收已取的序列值;
  • Sequence 适合生成技术主键,不适合生成要求绝对连续的业务流水号。

如果业务要求发票号、单据号严格连续,要用专门的业务编号方案,而不能直接依赖普通 Sequence。

完整版教学

一、Sequence 为什么是独立对象

Oracle 传统上不像某些数据库那样只在列上写 AUTO_INCREMENT。它把序列号生成抽成独立对象:

CREATE SEQUENCE order_seq;

这让序列可以被多个表或多个语句使用,也可以独立配置缓存、步长、最大值、循环等属性。

二、NEXTVAL 和 CURRVAL 怎么用

常见插入:

INSERT INTO orders(id, amount)
VALUES (order_seq.NEXTVAL, 100);

如果当前会话已经调用过 NEXTVAL,可以用:

SELECT order_seq.CURRVAL FROM dual;

CURRVAL 不是全局当前最大值,而是当前会话最近一次拿到的值。会话没调用过 NEXTVAL 前,不能直接使用 CURRVAL

三、为什么 Sequence 会跳号

Sequence 不保证连续。常见跳号原因:

  • 事务拿到序列值后回滚;
  • 使用缓存后数据库异常重启;
  • 多会话并发取号;
  • RAC 多实例缓存序列;
  • 手动调整序列值。

例如事务 A 获取了 1001,随后回滚,1001 不会被重新发给别人。这样做是为了性能和并发安全。

四、Sequence 适合技术主键

技术主键的目标是唯一、稳定、方便关联,不要求业务连续。Sequence 很适合这种场景。

但业务流水号不同,例如发票号可能要求严格连续、可审计、不能跳号。此时如果直接用 Sequence,回滚或故障导致的跳号就会变成业务问题。

正确做法是区分:

  • 技术 ID:用 Sequence 或 identity;
  • 业务编号:用业务规则生成,配合状态、审计和补偿机制。

五、Identity column 和 Sequence 的关系

Oracle 后续版本支持 identity column,可以在列定义上声明自动生成值,使用上更接近其他数据库的自增列。

但从理解角度看,identity 仍然是数据库自动生成数字的机制,和 Sequence 思路相通。面试时可以说:传统 Oracle 常显式使用 Sequence,现代版本也可以用 identity 简化自增主键定义。

六、常见误区与追问

用途能否用普通 Sequence原因
技术主键 ID适合只要求唯一稳定,不要求连续
发票号、监管流水不宜直接用通常要求连续、审计、可解释
高并发取号适合配 CACHE性能好但可能跳号

易错点:Sequence 保证按规则发唯一值,不保证没有空洞。把“唯一递增”和“严格连续”混为一谈,是这题最常见的坑。

数字例子:CACHE 20 时,实例可能一次缓存 20 个号。已经缓存到 1001 到 1020,如果数据库在只用到 1005 时异常重启,1006 到 1020 可能就丢失不用;再启动后可能从 1021 继续。事务回滚也一样,拿到 1005 后回滚,1005 不会退回给别人。

  • 误区:Sequence 生成的值一定连续。 回滚、缓存、故障、RAC 多实例都可能造成跳号。
  • 误区:CURRVAL 是全库当前最大序列值。 CURRVAL 是当前会话最近一次 NEXTVAL 的值,未调用过 NEXTVAL 不能直接用。
  • 误区:Sequence 只能给一张表用。 Sequence 是独立对象,可以被多个语句或表引用,但是否共享要看业务设计。
  • 追问:CACHE 为什么会导致跳号? 缓存值在内存中,实例异常后未使用的缓存号可能丢失,但换来更少的取号开销。
  • 追问:Identity column 和 Sequence 有什么关系? Identity 是更接近自增列的声明方式,底层思想仍是数据库生成数字,传统 Oracle 常显式用 Sequence。
  • 追问:严格连续业务号怎么做? 要单独设计业务编号、状态、审计、作废和补偿机制,不能直接依赖普通 Sequence。

七、加强记忆

Oracle Sequence 记住“独立取号器”:NEXTVAL 取下一个值,回滚不退号,缓存会提升性能但可能跳号。它适合技术主键,不适合要求绝对连续的业务单据号;连续编号要单独设计业务编号体系。