热块竞争源于数据访问模式和对象设计,需通过AWR的Segments by Global Cache Buffer Busy定位争用段,结合v$session_wait与dba_extents查具体对象,相邻block#集中出现即为热块。

热块竞争不是配置问题,而是数据访问模式和对象设计问题;不改访问逻辑或对象结构,只调参数基本无效。
怎么快速定位热块对象
别等业务报障才查——AWR里Segments by Global Cache Buffer Busy直接列出争用最严重的段。如果看到同一张表的主键索引或序列值索引(比如IDX_ORDER_LIST_OLNBR_1)反复出现,基本就是根因。
确认是不是真热块,执行:
SELECT p1 "file#", p2 "block#", p3 "class#"
FROM v$session_wait
WHERE event IN ('gc buffer busy acquire', 'gc buffer busy release');
再用dba_extents反查对象:
-
&file和&block代入上一步结果 - 注意
relative_fno而非file_id,否则可能跨表空间误判 - 如果多个
block#集中在相邻范围(比如差值
为什么反转索引(reverse index)能缓解争用
右向增长的索引(如自增ID、时间戳)会让新插入全部挤在同一个叶块,RAC下所有节点都抢这个块,触发大量gc buffer busy acquire。反转索引把10001→10001变成10001→10001(十六进制反转),打散写入位置。
但要注意:
- 不能用于范围查询频繁的字段(
WHERE create_time BETWEEN ...会失效) - 建索引时必须显式加
REVERSE关键字:CREATE INDEX idx_rev ON t(id) REVERSE; - 重建后需检查执行计划,避免原本走索引的查询退化为全表扫描
分区表设计必须匹配访问模式
按天分区的流水表,如果所有写入都落在最新分区(比如PARTITION P20260721),那只是把热块从“全表”缩小到“单分区”,争用没本质缓解。
真正有效的做法:
- 对高并发插入场景,优先用
HASH分区(比如按订单ID哈希到64个分区),让写入天然分散 - 若必须用
RANGE,至少叠加二级LIST或HASH分区,避免单一分区成为瓶颈 - 验证分区效果:查
v$segment_statistics中各分区的gc buffer busy等待次数,差距应大于5倍
应用层隔离比数据库调优更直接
RAC不是为“所有节点疯狂写同一张表”设计的。如果业务允许,把不同模块路由到固定节点(比如订单写节点1、支付写节点2),能彻底绕过Cache Fusion开销。
实施要点:
- 通过SCAN Listener + 客户端连接字符串中的
INSTANCE_NAME控制初始连接节点 - 避免依赖VIP漂移——它不保证会话持续绑定同一节点
- 关键事务开启
ALTER SESSION SET INSTANCE=...;强制绑定,但需确保应用支持会话级切换
热块问题的复杂点在于:它永远是数据库、应用、硬件三层耦合的结果。单独看gc buffer busy acquire等待,可能源于SQL写法、索引设计、分区策略、网络延迟甚至存储IO响应时间——任何一个环节偏差,都会在RAC环境下被放大。


















