RAC中分区亲和性指通过SERVICE+INSTANCE_AFFINITY+业务路由协同,使特定分区主要由固定实例服务以减少GC等待;仅对RANGE/LIST/HASH分区有效,需应用按分区键连接对应service,否则仍触发跨实例请求。
什么是 RAC 中的分区亲和性(Partition Affinity)
rac 里表做了分区,不等于数据就自动“贴”在某个实例上;默认情况下,每个分区的数据可能被任意实例访问,gc(global cache)请求随之频繁——尤其是高并发 dml 场景下,gc buffer busy acquire 或 gc cr block busy 等等待会明显上升。
所谓“亲和性”,是指让特定分区主要由固定实例服务,减少跨实例块请求。它不是 Oracle 自动启用的功能,而是靠人为设计 + 配置实现的局部性控制。
- 只对范围(
RANGE)、列表(LIST)、哈希(HASH)分区表有效,组合分区需看子分区类型 - 依赖于
SERVICE+INSTANCE AFFINITY+ 分区键与业务路由逻辑协同,不是单靠 DDL 就能生效 - 12c 及以后支持
AUTO模式(ALTER TABLE ... MODIFY PARTITION ... ONLINE SERVICE = 'xxx'),但底层仍需 service 绑定到单一实例
怎么用 SERVICE 和 INSTANCE AFFINITY 控制分区访问路径
Oracle 不提供“把分区绑定到实例”的直接语法,而是通过 service 的运行节点 + 应用连接路由来间接实现。关键在于:让某类 SQL 总是连到特定实例,且该实例恰好服务对应分区。
- 创建专用 service,并指定
INSTANCE_AFFINITY = TRUE和FAILOVER_TYPE = NONE(避免 failover 打乱亲和) - 用
srvctl add service -d <code>db_name-ssales_us-rrac1-arac2明确指定首选(-r)和可用(-a)实例 - 应用层必须按业务维度(如
region_code、tenant_id)选择对应 service 连接,不能全走SERVICE_NAME = orcl这种全局 service - 分区键值需与 service 路由规则对齐,例如:所有
region_code = 'US'的记录放在P_US分区,且只通过sales_usservice 访问
否则即使分区存在,SQL 还是可能被负载均衡到其他实例,触发远程 GC 请求。
为什么 HASH 分区 + SERVICE 亲和容易失效
HASH 分区本身是为均匀分布设计的,分区号由 MOD(HASH_VALUE(key), num_partitions) 决定,和实例无关。如果没配合应用路由,哪怕你把 P1 分区“倾向”给 rac1,只要应用连的是 rac2 并查 P1,照样产生 GC。
- 不要单独依赖
ALTER TABLE ... MODIFY PARTITION P1 ONLINE SERVICE = 'svc1'就以为搞定——这仅影响 DDL 期间的 service 关联,不改变运行时的访问路径 - 若业务无法按分区键做连接路由(比如混合查询多个 region),亲和性收益极低,甚至因 service 切换引入额外延迟
- 19c 引入的
DBMS_PART.CONSOLIDATE可重分布数据以匹配 service,但需停写、锁表,生产慎用
GC 等待没降?先检查这几个地方
加了 service、改了分区、应用也切了连接,GC 等待还是高——大概率卡在细节上。
- 确认 service 真正在目标实例运行:
crsctl stat res -t | grep sales_us,别只看srvctl config配置 - 查
v$session的service_name和inst_id是否一致,不一致说明连接没走对 service 或被 listener 转发了 - 检查是否用了绑定变量导致 cursor sharing 失效,让原本应走
sales_us的语句被缓存进sales_eu实例的 shared pool - 留意索引分区:如果本地索引没对齐分区键,或全局索引未按 service 拆分,DML 仍会触达多实例
亲和性不是开关,是端到端链路的对齐。少一个环节,GC 就照常等。










