段头争用是多个会话并发修改同一段的段头块引发buffer busy waits(p3=4),本质是空闲空间管理热点,区别于hw锁争用;常见于非分区小表、未分区lob或assm下初始bitmap块争用,需结合p1/p3解析定位段头块并分区或调整freelist组缓解。

什么是段头争用(segment header contention)
段头争用本质是多个会话同时请求修改同一段(segment)的段头块(segment header block),触发 buffer busy waits 等待,P3 值为 4 时明确指向段头块。它和 HW 锁争用(enq: HW - contention)常伴生但机制不同:HW 锁管高水位线推进,段头争用管空闲空间管理(如 freelist/freelist group 分配、ASSM 的 bitmap 块更新)。常见于高并发 INSERT 场景下的非分区小表、未启用 ASSM 的手动管理表空间,或 LOB 段未分区时。
怎么快速确认是不是段头争用
不能只看等待事件名,必须结合 P3 和块类型交叉验证:
- 查
v$session_wait中event = 'buffer busy waits'且p3 = 4的会话 - 用
DBMS_UTILITY.data_block_address_file和DBMS_UTILITY.data_block_address_block解析p1(RDBA),再查dba_extents定位对象 - 若定位到的块属于
SEGMENT_TYPE IN ('TABLE', 'INDEX', 'LOBSEGMENT')且block_id = segment_header_block(即 extent 的第一个块),基本可断定是段头争用 - 注意区分:如果是
UNDO HEADER或SYSTEM表空间中的段头,问题根源在回滚段或数据字典缓存,不是业务表本身
ASSM 下段头争用的典型诱因与应对
Oracle 10g+ 默认使用 ASSM(Automatic Segment Space Management),但 ASSM 并不自动消除段头争用——它的 bitmap 块(尤其是第一个 bitmap 块)就是新的“段头热点”。以下情况极易触发:
- 单个大表在高并发 INSERT 时,所有会话都试图更新同一个 initial bitmap 块来分配新块
-
CREATE TABLE未指定SEGMENT CREATION IMMEDIATE,首次 INSERT 才建段,导致初始 bitmap 块集中争用 - 表虽启用了 ASSM,但未做分区,整个段只有一个 bitmap 管理域
- LOB 字段未随表分区,其
LOBSEGMENT仍是单一段,bitmap 块成瓶颈
解决动作优先级:对高频写入表立即加 hash 或 range 分区(哪怕只分 4–8 个),让每个分区有独立 bitmap 块;LOB 必须配合表分区,否则单独操作 LOB 存储参数无效。
手动段管理(MSSM)下如何缓解
老系统仍用 MSSM(freelist 管理)时,段头争用直接表现为 freelist 组争用。关键不是加 freelist 数量,而是确保物理分布合理:
- 检查当前 freelist 设置:
SELECT table_name, freelists, freelist_groups FROM dba_tables WHERE table_name = 'YOUR_TABLE'; - 若
freelists = 1且并发高,先设为 CPU 核数 × 2(如 8 节点 RAC 设 16),但上限不宜超 32 - 必须同步设
freelist_groups > 1(至少等于实例数),否则 RAC 下跨实例无法并行获取空闲块 - 执行
ALTER TABLE t ALLOCATE EXTENT预分配足够大的初始 extent(≥ 当前最大 extent),减少后续频繁扩展段头的操作 - 真正容易被忽略的是:MSSM 表迁移到 ASSM 后,若未重建索引或未
SHRINK SPACE,旧 freelist 结构残留可能干扰 bitmap 分配逻辑
段头争用从来不是孤立现象——它常和 gc buffer busy acquire(RAC)、latch: cache buffers chains(热链)混发。动手前务必用 AWR/ASH 分离出主导等待类型,否则调 freelist 或扩 buffer cache 只会让问题更隐蔽。











