Oracle 19c中IDENTITY列无法直接查询NEXTVAL,因其底层隐藏序列不对外暴露;需查USER_TAB_IDENTITY_COLS视图的LAST_NUMBER字段获取下个值,该值即为NEXTVAL结果。
identity列不能直接替代序列,它只是底层用序列封装了一层;真要优化高并发插入性能,得动序列本身的参数,而不是换语法。
为什么IDENTITY列查不到NEXTVAL值
Oracle 19c 中 GENERATED AS IDENTITY 列背后会自动创建一个隐藏序列(名字形如 ISEQ$$_XXXXX),但这个序列不对外暴露给 SELECT seq.NEXTVAL FROM DUAL。你无法像普通序列那样显式调用它,也不能重置或共享。
- 想看下一个将生成的值?查
USER_TAB_IDENTITY_COLS视图里的LAST_NUMBER字段,它就是下一次NEXTVAL的结果 - 想提前预取一批ID用于业务逻辑?IDENTITY做不到——必须用显式序列 +
NEXTVAL - 想让多个表共用同一套编号规则(比如订单号、工单号都从同一序列取)?只能用序列,IDENTITY绑定死在单表上
高并发下序列争用的真实瓶颈在哪
问题不在“用不用IDENTITY”,而在序列的 CACHE 和 SCALE 配置。默认 CACHE 20 在每秒上千次插入时,会导致索引最右叶块反复被更新,出现 enq: SQ - contention 等待事件。
-
CACHE值太小 → 频繁访问数据字典表SEQ$,增加闩锁竞争 -
CACHE值太大 → 实例崩溃可能丢失最多CACHE个未用数值(对主键ID通常可接受) - Oracle 19.10+ 自动启用
Sequence dynamic cache resizing,但只对显式序列生效,对IDENTITY背后的隐式序列无效 - 真正缓解RAC环境争用的是
SCALE选项(需显式创建:CREATE SEQUENCE s1 SCALE),它通过实例/会话偏移打散写入热点
什么时候该坚持用显式序列而不是IDENTITY
IDENTITY看着简洁,但掩盖了控制权。以下场景必须用显式序列:
- 需要在INSERT前就拿到ID(比如作为关联子表外键、写入日志、生成业务流水号)→ 用
seq.NEXTVAL赋值给变量 - 批量插入(
INSERT /*+ APPEND */)时要保证ID连续且可控 → IDENTITY在直接路径插入中行为受限,序列更稳定 - 需要循环(
CYCLE)、指定最大值(MAXVALUE)、或跨多表复用 → IDENTITY不支持这些 - DBA需要监控或调整序列行为(比如清空缓存、修改
INCREMENT BY)→ 隐式序列不可见、不可管
一个容易被忽略的兼容细节
IDENTITY列定义里 GENERATED ALWAYS AS IDENTITY 和 GENERATED BY DEFAULT AS IDENTITY 行为差异极大:
-
ALWAYS:任何显式插入值都会报错ORA-32795,强制走自增 -
BY DEFAULT:允许手动插入值,只有值为NULL或未提供时才触发自增 —— 这意味着应用层如果漏传字段,可能意外覆盖ID生成逻辑 - 如果你依赖“绝对不许人工干预ID”的语义,必须选
ALWAYS,且禁用CYCLE,否则可能重复



















