是\_undo\_autotune在动态捣乱;Oracle 19c默认开启该隐含参数,导致SMON频繁开关undo段,高并发下堵塞dc_rollback_seg latch,引发enq: US-contention等待。
确认是不是 _undo_autotune 在动态捣乱
oracle 19c 默认开启 _undo_autotune,它会让 smon 频繁上线/下线 undo 段,但高并发 dml 下这反而会卡住 dc_rollback_seg 行缓存 latch,引发大量 enq: us - contention 等待。这不是空间真不够,而是分配路径被堵死。
先执行:SHOW PARAMETER _undo_autotune
如果返回 TRUE,基本就是它在后台反复震荡。
- 查最近一小时 undo 段状态波动:
SELECT TO_CHAR(sample_time, 'HH24:MI'), COUNT(*) FROM v$undostat GROUP BY TO_CHAR(sample_time, 'HH24:MI') ORDER BY 1;分钟级数量剧烈跳变(比如从 30 → 80 → 20),说明 autotune 正在抢着开关段 - 对比
v$rollname和v$transaction:若在线段数远超当前活跃事务数,且很多状态是PENDING或刚从OFFLINE变成ONLINE,就坐实是 autotune 引发的震荡
立即禁用自动调优并稳住 online undo 段数量
_undo_autotune=FALSE 不需要重启,SCOPE=BOTH 即刻生效。别等扩容或调 UNDO_RETENTION,先让分配逻辑停下来。
执行:ALTER SYSTEM SET "_undo_autotune" = FALSE SCOPE=BOTH
- 查当前在线段数:
SELECT COUNT(*) FROM v$rollname WHERE status = 'ONLINE' - 手动固定数量:用
ALTER ROLLBACK SEGMENT <name> ONLINE/OFFLINE调整到稳定值;建议设为峰值事务数 × 1.5,但不超过 64 - 顺手检查
v$undostat的unxpstealcnt:如果持续 > 0,说明 active undo 正被偷用,此时UNDO_RETENTION设太低,需同步上调——但别盲目拉到 18000 秒,先看最长查询耗时
别把空间不足和争用混为一谈
现象相似,根因相反,处理方向完全反着来:
- 如果是空间不足:
DBA_UNDO_EXTENTS中ACTIVE少、EXPIRED多,UNDO_TABLESPACE使用率长期接近 100%,且v$session_wait里enq: US - contention的seconds_in_wait普遍很长 - 如果是争用:
EXPIRED很少,UNEXPIRED占大头,v$enqueue_stat中total_req#和total_wait#都很高,但UNDO_TABLESPACE实际使用率可能才 60%~70% - 额外验证:查
v$rollstat的waits列,如果某几个段的等待次数明显高于其它段,说明争用集中在特定段上,不是全局空间问题
绕过 autotune 后怎么避免拍脑袋定数量
关掉 _undo_autotune 后,不能靠经验或峰值猜一个固定值。得结合业务节奏和历史负载来校准:
- 用 AWR 报告看过去 7 天每小时的
v$transaction最大并发数,取 P95 值再乘以 1.5 - 检查
v$undostat的maxquerylen和ssolderrcnt:前者决定最低 retention 需求,后者非零说明已发生 ORA-01555,需回溯长事务源头 - RAC 环境要特别注意:
_rollback_segment_count是实例级参数,每个节点得单独设;别漏掉ALTER SYSTEM SET "_rollback_segment_count" = <n> SCOPE=BOTH
最易被忽略的一点:禁用 autotune 后,UNDO_RETENTION 才真正起作用;之前它一直被自动覆盖,调了也白调。


















