<p>enq: HW - contention 频繁源于多会话争抢同一段HWM推进权限,需通过ASH/v$session_wait查P3值,拆解为文件号和块号后联查dba_extents定位热点段,常见于LOB段、流水日志表及未分区大表。</p>

enq: HW - contention 在 Oracle 12c 的 AWR 报告中频繁出现,说明多个会话正串行争抢同一段(segment)的高水位线(HWM)推进权限——这不是配置偏低或资源不足的表象,而是空间分配逻辑被高频触发的信号。
怎么确认是哪个表/段在争用
关键不是猜,是查 P3 参数定位段头块,再反推对象:
- 从
v$session_wait或 ASH 中抓出正在等的P3值(例如20974058) - 用
DBMS_UTILITY.DATA_BLOCK_ADDRESS_FILE和DBMS_UTILITY.DATA_BLOCK_ADDRESS_BLOCK拆解它:SELECT DBMS_UTILITY.DATA_BLOCK_ADDRESS_FILE(20974058) AS file#, DBMS_UTILITY.DATA_BLOCK_ADDRESS_BLOCK(20974058) AS block# FROM dual; - 再查
dba_extents定位段:SELECT owner, segment_type, segment_name FROM dba_extents WHERE file_id = &file_id AND &block_id BETWEEN block_id AND block_id + blocks - 1;
- 常见结果:LOB 段、流水日志表(如
CPOE_ORD_CA_SYSTEM_REL)、未分区的大表(如XML_INFO_201708)
注意:P2 是表空间号,若为 1 或 2,要警惕是不是 undo 表空间里的回滚段在扩展——这通常意味着大批量 UPDATE 触发了回滚段 HWM 推进。
为什么 INSERT / UPDATE 会反复触发 HW 锁
HW 锁本质是排他锁(mode=6),每次推进 HWM 都必须独占获取。以下操作会高频触发它:
- 多进程并发向同一张非分区表执行
INSERT,尤其带/<em>+ APPEND </em>/—— 直接路径写始终在 HWM 上方分配空间,跳过缓冲区,但锁争用更集中 - 向含
CLOB/BLOB字段的表插入或更新,LOB 段本身有独立 HWM,且 CHUNK 分配易碎片化 - 索引键值单调递增(如序列主键),导致右侧叶子节点频繁分裂,需不断扩展索引段 HWM
- 表空间开启
AUTOEXTEND且剩余空间不连续,每次扩展都伴随物理格式化新数据文件块,延长 HW 锁持有时间
不要误以为调大 SGA 或增加 UNDO_RETENTION 能缓解——这些和 HW 锁无关。
分区和预分配是见效最快的两个手段
对已确认的热点表,别只调参数,直接改结构:
- 对插入密集型流水表(如日志、交易明细),优先建
HASH或RANGE分区,把 HWM 推进分散到多个子段:-
HASH分区能均匀打散并发写入压力,实测可降enq: HW - contention次数 90% 以上 -
RANGE分区适合按时间字段(如STAMP)切分,避免老分区被反复写入
-
- 对无法立即分区的表,手动预分配足够多的
EXTENT:ALTER TABLE CPOE_ORD_CA_SYSTEM_REL ALLOCATE EXTENT (SIZE 10M);
连续分配可减少后续自动扩展频次;但注意别在 ASSM 表空间里过度预分配,可能加剧位图块(L3 block)争用
真正容易被忽略的是:LOB 段默认不继承主表分区策略,即使主表已分区,CLOB 列仍可能落在单个 LOBSEGMENT 中——必须显式指定 LOB (XML_DATA) STORE AS SECUREFILE (TABLESPACE ...) 并配合分区语法。


















