latch: redo allocation 高争用本质是多会话争抢redo log buffer分配指针,源于高并发小事务下闩锁串行化瓶颈;需检查_log_parallelism_dynamic是否启用、评估pvrs适用性、合理设置log_buffer(100–300mb)并绑定lgwr cpu,而非盲目调大日志或优化磁盘。
oracle 11g 中 latch: redo allocation 高争用,本质是多个会话同时申请 redo log buffer 空间时撞在同一把闩锁上,不是日志文件慢,而是“抢内存格子”太挤。必须从分配路径入手,不能只调大 log_buffer。
为什么 latch: redo allocation 会飙升
Redo Allocation Latch 保护的是 Redo Log Buffer 的“分配指针”,每次 INSERT/UPDATE 生成 redo 条目前,进程都得先拿到这把 latch 才能确定写入位置。在高并发 OLTP 场景下(比如每秒上千次小事务),大量会话几乎同时触发分配请求,就会集中争抢——尤其当系统 CPU 核数多、_log_parallelism_dynamic 未生效或被禁用时,所有分配仍压在单个 latch 上。
- 现象:AWR 中
latch: redo allocation的miss_pct> 5%,且sleeps显著上升 - 注意:
log file sync高通常伴随它,但二者不是因果关系;前者是“写磁盘慢”,后者是“抢缓冲区入口慢” - 常见误判:看到日志写慢就去加日志文件大小或换更快磁盘,实际瓶颈根本不在磁盘侧
检查当前是否启用动态并行分配
Oracle 11g 默认开启 _log_parallelism_dynamic,但若被显式设为 FALSE 或隐含参数被覆盖,就会退化回单 latch 模式。
- 执行:
SELECT ksppinm, ksppstvl FROM x$ksppi a, x$ksppcv b WHERE a.indx = b.indx AND ksppinm LIKE '%_log_parallelism%'; - 关键看:
_log_parallelism_dynamic值是否为TRUE;若为FALSE,且_log_parallelism_max≤ 1,则确认已退化 - 风险操作:不要直接改
_log_parallelism_max到很高值(如 8+),它受 CPU_COUNT 和实际负载限制,盲目调高反而增加管理开销
强制启用私有重做流(PVRS)缓解小事务冲击
PVRS 是 11g 对小事务的优化机制:为每个会话分配独立的私有 redo 内存段(64–128KB),绕过公共 buffer 分配路径,天然避开 redo allocation latch。
- 前提:事务足够小(单次 DML 生成 redo _use_private_redo 是否为
TRUE) - 验证是否生效:
SELECT sid, value FROM v$sesstat s, v$statname n WHERE s.statistic# = n.statistic# AND n.name = 'redo entries (private)' AND value > 0;—— 有非零值说明 PVRS 已介入 - 若未启用,不建议硬启;优先确保
_use_private_redo未被设为FALSE,并避免在应用中频繁COMMIT超小事务(如逐行提交)
调整 LOG_BUFFER 与绑定 CPU 的实操边界
LOG_BUFFER 不是越大越好。超过一定阈值(通常 200–400MB)后,分配竞争不降反升,因为大 buffer 导致分配指针移动更慢、自旋时间更长。
- 安全范围:OLTP 系统建议控制在
100M–300M;若当前 > 400M,可尝试降至256M并观察 latch miss 变化 - CPU 绑定辅助:在 Linux 上,将 LGWR 进程绑定到专用 CPU(如
taskset -c 3 oraccpu),减少上下文切换干扰其分配逻辑 - 绝对避免:用
ALTER SYSTEM SET LOG_BUFFER=xxx SCOPE=SPFILE在线修改——该参数不可动态改,必须重启,且重启期间所有未刷盘 redo 都会丢失
真正卡住的从来不是磁盘速度,而是那一小段共享内存里的分配指针。盯住 v$latch 里 redo allocation 的 spin_gets 和 sleeps 比值,比看 log file sync 平均等待时间更能定位根因。











