sequence跳号是oracle为性能主动取舍的正常现象,源于rac下cache与noorder组合导致各节点预取号段后异常丢弃;单实例亦存在,nocache仅降低跳号概率但不消除,且严重牺牲性能。
sequence 跳号是正常现象,不是 bug
oracle rac 环境下 sequence 出现跳号(比如从 100 直接到 105),根本原因在于 cache 和 noorder 的组合行为。这不是数据错乱,也不是配置失误,而是 oracle 为性能做的主动取舍。
每个 RAC 节点会从共享缓存中预取一段序列号(如 CACHE 20 就取 20 个),各自维护本地内存池。节点崩溃、实例重启或缓存刷出时,未用完的号段直接丢弃——跳号由此产生。
-
CACHE值越大,跳号幅度可能越大,但序列生成性能越高 -
NOORDER表示不保证跨节点的递增顺序(RAC 默认就是它),启用ORDER会强制全局同步,性能暴跌,一般不建议 - 单实例库即使开
CACHE也会跳号(比如实例异常终止),只是不明显
什么时候必须禁用 CACHE?
只有在「绝对不允许跳号」且能接受性能代价的场景下,才考虑 NOCACHE。典型例子:财务系统要求凭证号严格连续、审计留痕不可断号。
但要注意:NOCACHE 并不能 100% 消除跳号——如果事务回滚了 NEXTVAL,那个号就永远丢失;或者并发高时频繁争用 SEQ$ 行锁,反而引发等待。
- 执行
ALTER SEQUENCE seq_name NOCACHE;后,每次调用NEXTVAL都要写重做日志+更新数据字典,TPS 显著下降 - RAC 下
NOCACHE + ORDER更慢,因为要跨节点协调,基本只用于极低频关键编号 - 别迷信
SELECT seq_name.CURRVAL FROM DUAL来“补漏”,它只返回当前会话已取过的值,无法找回丢弃的号段
更现实的优化路径:接受跳号,隔离风险
绝大多数业务其实不需要真正连续的数字,只需要唯一、单调递增、便于索引。跳号不影响主键约束、不影响查询、不影响应用逻辑——真正要防的是人肉对账时的心理落差。
与其硬刚数据库机制,不如在应用层或展示层处理:
- 用
ROW_NUMBER() OVER (ORDER BY create_time)生成展示用序号,和主键物理 ID 分离 - 导出报表时加一列「逻辑序号」,由应用或视图计算,不依赖
SEQUENCE - 审计需求明确写进 SLA:“编号允许跳号,跳号不视为数据异常”,避免后期扯皮
- 监控
DBA_SEQUENCES.CACHE_SIZE和实际跳号频率,若CACHE 50却平均每次跳 200+,说明有实例频繁重启,该查 OS 或 CRS 日志了
NOORDER 是 RAC 下的合理默认,别乱改
RAC 中 NOORDER 不是偷懒选项,而是性能基石。强行加 ORDER 会让所有 NEXTVAL 请求串行化到一个节点(通常是第一个启动的实例),该节点瞬间成为瓶颈,enq: SQ - contention 等待飙升。
如果你看到文档说“加 ORDER 可避免跳号”,那是误导——ORDER 只保证获取顺序,不保证不跳号。缓存段照样丢,只是丢得“有序”而已。
-
CREATE SEQUENCE seq_name START WITH 1 INCREMENT BY 1 CACHE 20 NOORDER;是 RAC 安全、高效的标准写法 - 不要在建表时用
DEFAULT seq_name.NEXTVAL依赖序列,DDL 执行时可能触发隐式序列调用,增加不可控跳号点 - 批量插入慎用
seq_name.NEXTVAL多次,改用INSERT ... SELECT seq_name.NEXTVAL FROM DUAL CONNECT BY LEVEL ,减少解析开销
跳号的本质是缓存与可用性的权衡。想彻底消灭它,就得放弃 RAC 的扩展性,或放弃序列的高性能。工程上没银弹,只有取舍清楚、边界明确。










