RAC中sequence必须设CACHE和NOORDER,否则高并发下因争抢DC_SEQUENCES缓存条目导致row cache lock和enq: SQ-contention飙升;CACHE过小或ORDER开启会加剧跨节点同步开销。

必须改 sequence 的 CACHE 和 ORDER 属性,否则 enq: SQ - contention 和 row cache lock 等待会持续飙升,这不是应用层重试能解决的。
为什么 RAC 中 sequence 一并发就卡住
根本不是序列值本身慢,而是 RAC 多节点争抢同一 row cache entry(DC_SEQUENCES)导致锁排队。每个 NEXTVAL 调用都要更新数据字典缓存,若没缓存或缓存太小,就会频繁触发 row cache lock 等待;如果还开了 ORDER,更会强制跨节点同步,引入 SV 锁和私网通信开销。
-
cache_size = 1或默认20:每取 20 个就要回源刷新,高并发下瞬间打满 row cache latch -
ORDER = YES:要求所有节点按严格递增顺序返回值,LMD 必须协调,延迟陡增 - 没配
NOORDER却又没设足够CACHE:各节点缓存段互不重叠但太窄,仍频繁争抢 DC_SEQUENCES
CREATE SEQUENCE 必须带的两个参数
新建 sequence 时,CACHE 和 NOORDER 是硬性组合,缺一不可。RAC 下不存在“既要顺序又要性能”的中间态。
- 用
CACHE 1000 NOORDER:每个实例预取 1000 个值到本地内存,彻底避开 row cache 争抢 - 禁用
ORDER:允许节点间数值跳跃(如 node1 给 1001–2000,node2 给 2001–3000),这是 RAC 可扩展性的代价 - 避免
NOCACHE:哪怕只写几条也绝对不用,它会让每次NEXTVAL都走磁盘+锁,直接拖垮系统
已存在 sequence 怎么安全调整
不能直接 ALTER SEQUENCE ... CACHE —— Oracle 不允许在线修改 CACHE 值。必须重建,且需业务窗口配合。
- 先查当前状态:
SELECT sequence_name, cache_size, order_flag FROM dba_sequences WHERE sequence_name = 'SEQ_ORDERS'; - 导出依赖该 sequence 的对象(如触发器、默认值),停写业务后
DROP+CREATE新 sequence - 重建语句示例:
CREATE SEQUENCE seq_orders START WITH 1000000 INCREMENT BY 1 CACHE 1000 NOORDER; - 注意:原 sequence 若被用作主键默认值(
DEFAULT seq.NEXTVAL),重建后需重新绑定
容易被忽略的隐性陷阱
改完 sequence 还卡?大概率是其他地方在偷偷放大争用。
- 应用层循环调用
NEXTVAL(比如 for 循环里每 insert 一次都取一个):应改用批量获取(SELECT seq.NEXTVAL FROM DUAL CONNECT BY LEVEL <= 100)再分发 - sequence 名被硬编码在多个模块,部分未同步更新:用
dba_dependencies扫描所有引用点 - 表上还有单调递增索引(如
CREATE INDEX idx_id ON t(id)):sequence 争用缓解了,但gc buffer busy acquire可能立刻接上,得同步加REVERSE或换前导列 - 底层表空间没启 ASSM:
SELECT segment_space_management FROM dba_tablespaces WHERE tablespace_name = 'USERS';返回MANUAL就得立刻切,否则 freelist 争用会掩盖 sequence 优化效果
真正难的不是改参数,而是在业务不允许停机、又不敢动 SQL 的前提下,精准定位哪个 sequence 在扛压、哪段代码在滥用 NEXTVAL——这需要结合 AWR 的 row cache lock P1 值反查 v$rowcache,再关联 dba_hist_active_sess_history 抽样 SQL_ID。


















