Oracle RAC中并发热块冲突须从数据分布与访问模式解决,右增长索引易致全局热块;HASH分区、INSTANCE_ID分流、反向索引+序列缓存为三大应对策略。
oracle
rac 中的并发热块冲突(本质是
和
)不是靠调参能根治的,必须从数据分布和访问模式入手。最有效的解法是让不同实例写入的数据天然分散在不同物理块上,避免跨节点争抢同一块。
为什么右增长索引在RAC里特别危险
像
这类基于自增 ID 或时间戳的右向增长索引,在 RAC 多节点并发插入时,所有新记录都挤在同一个索引叶子块末尾——这个块就成了“全局热块”。每个节点都要申请当前块的最新版本,触发大量
和
等待。
典型现象:AWR 中
排进 Top 5,平均等待毫秒数常超 100ms,甚至上千
根本原因:索引键值局部性太强,导致 buffer 访问高度集中
别指望只加
或调
——这些只能缓解表层症状
用 HASH 分区替代右增长主键索引
对高频插入的表(如订单、日志),把主键或唯一索引建在
分区上,强制数据打散。比如原表按
主键插入,现在改用
做哈希分区,16 个子分区对应 16 个独立的索引段。
操作路径:
注意必须是
分区索引,否则无法跨分区去重
如果原索引是唯一约束,需确认业务允许哈希后仍保持逻辑唯一(通常没问题,因哈希只是物理分布策略)
重建后,原来集中在 1~2 个块的插入压力,会均匀落到 16 个不同块上,
等待直接下降 70%+
表级复合分区 + INSTANCE_ID 字段分流
RAC 场景下,最彻底的隔离方式是让每个实例只写自己的数据段。这需要应用配合,在插入时显式带上
,再以此字段做范围分区,最后对业务主键做子分区。
oracle知识库
oracle知识库下载
下载
建表示例:
插入时必须带值:
关键点:分区键
必须参与所有 DML 的 WHERE 条件,否则优化器可能跳过分区裁剪,导致跨分区扫描
该方案能几乎消除
,但要求应用层改造,且查询必须带上
才高效
反向索引与序列缓存的配合使用
对于无法改表结构的老系统,可临时用反向索引(
)打散物理聚集度。但要注意它仅适用于等值查询,范围查询会失效;且 Oracle 12c 后已不推荐,优先选 HASH 分区。
创建:
副作用:
类查询会退化为全索引扫描
必须同步调大序列缓存:
,减少
引发的间接热块
反向索引无法解决 ITL 争用,若出现大量
,还得调高
和
真正难的不是选哪种技术,而是判断哪一层在漏——是索引设计没考虑分布式写入,还是应用没做实例感知,又或者缓冲池参数掩盖了本该暴露的数据分布缺陷。一旦看到
和
同时飙升,基本可以确定是物理数据布局和并发模型不匹配,这时候修 SQL 或加内存都是白忙。
gc buffer busy acquiregc buffer busy releaseIDX_ORDER_LIST_OLNBR_1gc cr block busygc buffer busy releasegc buffer busyPCTFREE_gc_lms_processesHASHORDER_IDORDER_ID % 16CREATE INDEX idx_order_hash ON customer_order(ORDER_ID) GLOBAL PARTITION BY HASH(ORDER_ID) PARTITIONS 16;GLOBALgcINSTANCE_IDCREATE TABLE customer_order (inst_id NUMBER, order_id NUMBER, ... ) PARTITION BY RANGE(inst_id) SUBPARTITION BY HASH(order_id) SUBPARTITIONS 8 (PARTITION p1 VALUES LESS THAN (2), PARTITION p2 VALUES LESS THAN (MAXVALUE));INSERT INTO customer_order VALUES (SYS_CONTEXT('USERENV','INSTANCE'), ...);inst_idgc buffer busyinst_idREVERSECREATE INDEX idx_order_rev ON customer_order(ORDER_ID) REVERSE;ORDER_ID BETWEEN 1000 AND 2000ALTER SEQUENCE order_seq CACHE 1000;enq: SQ - contentionenq: TX - allocate ITL entryINITRANSMAXTRANSgc buffer busyenq: TX