直接调大cache值并强制指定noorder是解决rac下enq: sq-contention的最有效手段;默认cache 20在多节点并发下易耗尽,引发高频跨节点同步等待。

enq: SQ - contention 等待飙升,不是因为序列本身慢,而是默认 CACHE 20 在 RAC 多节点下触发高频跨节点协调——每次号段用完,所有实例就得抢 DFS 锁去分配下一号段,走的是高开销集群消息路径。
CACHE 20 在 RAC 下为什么等于“自找排队”
- RAC 每个实例独立缓存号段:
CACHE 20意味着每个节点最多预占 20 个值;双节点并发时,40 个值可能几毫秒就耗尽 - 号段用完后,必须通过全局队列(如
SVS或DFS lock handle)协商“谁来领下一段”,这个过程要发集群消息、等响应、加锁、更新SEQ$表 -
v$enqueue_stat中SQ类等待陡增,AWR里 “enq: SQ - contention” 占 DB Time 超过 10% 是典型信号 - 实测:双节点各插 4 万行,
NOCACHE耗时 2100 秒,CACHE 1000仅需 55 秒——差 38 倍
为什么只改 CACHE 不加 NOORDER 是白忙
-
ORDER模式强制全局有序,哪怕CACHE 1000,每次切换号段仍要跨节点确认“你没用过这个值”,走的还是SV锁路径 -
NOORDER才真正让CACHE生效:各实例各自维护本地号段,彻底消除协调需求 - 加了
NOORDER后:gv$sequence显示各实例LAST_NUMBER差几百上千是正常现象,不是故障 - 副作用是 ID 不再严格递增(如实例 1 出 101–200,实例 2 同时出 201–300,但网络延迟可能导致 201 先入库),绝大多数业务(订单号、日志流水)只依赖唯一性,不依赖顺序
ALTER SEQUENCE CACHE N 为什么经常无效
-
ALTER SEQUENCE my_seq CACHE 200不会改变已有ORDER属性,旧序列照卡 - 必须显式带
NOORDER:例如ALTER SEQUENCE my_seq CACHE 1000 NOORDER - 修改后,已连接会话中缓存的号段仍按原规则用完才切换;新会话立即生效
- 更安全的做法是新建序列:
CREATE SEQUENCE s1 NOORDER CACHE 200,然后改应用指向新序列
LMS 进程调度没配实时,再大 CACHE 也救不了
- 序列争用已引发 GC 请求排队时,若
LMS进程没跑在SCHED_FIFO实时调度下,响应延迟会雪上加霜 - 检查命令:
ps -eo pid,comm,cls,pri,rtprio,%cpu | grep LMS,cls列必须是ff或rr(不能是ts) - 配置需两步:确保
_highest_priority_processes含LMS*,且/etc/security/limits.conf有oracle soft rtprio 99 - 改完必须发
kill -SIGUSR2 <lms_pid></lms_pid>重载调度策略,否则不生效
真正难的从来不是单点调参,而是把 NOORDER、合理 CACHE(50–500 起步,高压可到 1000)、LMS 实时调度三者一次配齐——缺一不可。尤其容易被忽略的是:LMS 调度策略改了不发信号,等于没改;而序列改了不带 NOORDER,等于白改。











