根本原因是SEQUENCE的CACHE过小(如默认20)且未设NOORDER,导致高频跨节点同步引发DFS锁争用;应查GV$_SEQUENCES定位低CACHE高ORDER序列,改为CACHE≥1000且显式添加NOORDER。
enq: SQ-contention 等待飙升,根本不是SQL写得慢
oracle rac 中 enq: sq-contention 等待暴增,99% 的情况不是应用 sql 有问题,而是某个或多个 sequence 的 cache 值太小——比如默认的 cache 20。每个实例最多缓存 20 个号,高频并发下几毫秒就耗尽,必须立刻抢着去更新 seq$ 表、申请 dfs 锁、跨节点同步,所有这些操作都串行化排队,enq: sq-contention 就是排队失败的“叫号纸”。
- AWR 里看到
enq: SQ-contention排进 Top 5,且平均等待超 300ms,基本可锁定是CACHE不够 -
P2值对应DBA_OBJECTS.OBJECT_ID,能直接定位到具体哪个SEQUENCE在拖后腿 - 别信“只是偶尔卡一下”,这是锁争用,会传染:一个序列卡住,连带 INSERT/UPDATE 语句全堵在解析或执行阶段
row cache lock 和 DFS lock handle 是连锁反应
CACHE 过小本质是把本该内存完成的操作,硬逼成物理 I/O + 全局协调。每次号段用完,就得刷 seq$ 表(触发 row cache lock),再走 RAC 内部队列协调分配(触发 DFS lock handle)。这两个等待事件从来不是孤立出现,而是一起爆。
-
NOCACHE序列:每次NEXTVAL都要物理更新seq$→row cache lock主力来源 -
CACHE但没NOORDER:号段切完还得全局确认顺序 →DFS lock handle主力来源 - 两者叠加(比如
CACHE 20 ORDER):物理写 + 全局锁 + 跨节点同步全来一遍,CPU 利用率瞬间拉满
CACHE 值不是越大越好,得看批量节奏
设 CACHE 50000 看似解气,但实例异常重启时,未用完的号段直接丢弃——比如刚用到 100234,宕机后下次从 150001 开始,跳号肉眼可见。这不是 bug,是设计取舍。
- 关键不是绝对值,而是它能否撑过一次典型批量操作周期:每秒插入 200 行、每批 50 条 →
CACHE 200就够用 1 秒 - 夜间批量导入峰值每秒 5000 行 →
CACHE 5000 ~ 20000更稳妥,已有客户稳定用到CACHE 50000 -
ALTER SEQUENCE只能改CACHE,不能改ORDER/NOORDER;要改后者,必须重建序列
NOORDER 不是可选项,是 RAC 下的强制前提
加了 ORDER 的 CACHE 序列,在 RAC 里等于没缓存。因为 ORDER 强制所有实例按全局单调递增分发号码,每次号段切换都得串行化到一个节点(通常是第一个启动的实例),那个节点瞬间变成单点瓶颈,v$lock 里 SQ 类锁激增,gv$sequence.LAST_NUMBER 在各节点几乎一致——这不是优化,是自废武功。
-
NOORDER允许各节点独立维护本地号段,彻底消除跨节点协调,enq: SQ-contention趋近于零 - 副作用是生成值不保证全局有序(如节点 A 出 101–200,节点 B 同时出 201–300,但网络延迟可能导致 201 先入库)
- 如果业务真依赖严格递增(极少见),别硬扛数据库机制,改用应用层 ID 生成器
NOORDER 必须和 CACHE 一起生效才有意义**;单独调大 CACHE 却保留 ORDER,性能几乎无改善。


















