查表空间使用率必须逐节点执行,因dba_free_space仅反映本地缓存空闲块,存在滞后与不一致;真实使用率需在每个rac节点分别查询并汇总。
查表空间使用率必须连到每个节点执行
oracle rac 中,dba_tablespaces 和 dba_data_files 是全局视图,但实际文件物理分布、读写热点、空间分配行为都发生在本地实例。直接在任一节点查 dba_free_space 只反映该节点缓存的空闲块信息,可能滞后或不一致。真实使用率必须逐节点查,否则会误判。
推荐做法是:在每个节点上分别运行以下语句(注意替换 TABLESPACE_NAME):
SELECT tablespace_name, ROUND(SUM(bytes)/1024/1024, 2) AS total_mb, ROUND(SUM(CASE WHEN autoextensible = 'YES' THEN maxbytes ELSE bytes END)/1024/1024, 2) AS max_mb, ROUND((SUM(bytes) - SUM(NVL(free_bytes,0)))/1024/1024, 2) AS used_mb, ROUND((SUM(bytes) - SUM(NVL(free_bytes,0))) * 100 / NULLIF(SUM(bytes),0), 2) AS pct_used FROM dba_data_files a LEFT JOIN ( SELECT file_id, SUM(bytes) AS free_bytes FROM dba_free_space GROUP BY file_id ) b ON a.file_id = b.file_id GROUP BY tablespace_name;
- 务必在每个节点用
sqlplus / as sysdba连接后执行,不能只查一个节点就推断全集群 -
DBA_FREE_SPACE的统计依赖于本地 LRU 管理器刷新,高并发 DML 后可能有几秒延迟,紧急判断时建议加ALTER SYSTEM CHECKPOINT后再查 - 如果某节点报
ORA-01219: database not open,说明该实例未正常启动,需先检查 CRS 和crsctl stat res -t
跨节点查数据分布得靠 ROWID + DBA_EXTENTS
RAC 中数据块物理分布在哪个节点,不由 SQL 决定,而由数据块所属的 extent 所在的 datafile 决定;而 datafile 本身是共享存储,所有节点都能访问。所谓“跨节点数据分布”,实际是指:哪些数据块当前被哪个节点的 buffer cache 频繁持有,或哪些 segment 的 extents 被哪些实例更常访问 —— 这需要结合对象级和缓存级视图。
最实用的定位方式是查 DBA_EXTENTS 关联 V$BH(buffer headers),但注意:V$BH 是实例级视图,只能看到本节点缓存的块。所以要拼出完整视图,得在每个节点执行:
SELECT /*+ ORDERED USE_NL(e bh) */
e.segment_name,
e.partition_name,
COUNT(*) AS cached_blocks
FROM dba_extents e,
v$bh bh
WHERE bh.file# = e.file_id
AND bh.dbablk BETWEEN e.block_id AND e.block_id + e.blocks - 1
AND e.owner NOT IN ('SYS','SYSTEM')
GROUP BY e.segment_name, e.partition_name
ORDER BY cached_blocks DESC;
- 这个查询结果只反映当前节点的 buffer cache 分布,不是磁盘分布 —— 磁盘上所有节点看到的
DBA_EXTENTS完全一致 - 若发现某大表在节点1缓存了80%的块,节点2只有5%,可能是
INSTANCE_NUMBER绑定不当,或应用连接没做 service-level 负载均衡 - 别用
ROWID的dbms_rowid.rowid_block_number()去“算”节点归属 —— RAC 中 block 不绑定节点,只绑定 cache owner,且 owner 可随时迁移
用 GV$ 视图汇总跨节点空间与缓存状态
想一次性看全集群各节点的表空间使用和 buffer 占用,必须用 GV$ 开头的视图,它们自动聚合所有在线实例的数据,并带 INST_ID 列标识来源节点。
例如查全集群表空间使用率(含 INST_ID):
SELECT inst_id, tablespace_name, ROUND(SUM(bytes)/1024/1024, 2) AS total_mb, ROUND((SUM(bytes) - SUM(NVL(free_bytes,0)))/1024/1024, 2) AS used_mb, ROUND((SUM(bytes) - SUM(NVL(free_bytes,0))) * 100 / NULLIF(SUM(bytes),0), 2) AS pct_used FROM gv$datafile a LEFT JOIN gv$free_space b ON a.inst_id = b.inst_id AND a.file# = b.file_id GROUP BY inst_id, tablespace_name ORDER BY inst_id, pct_used DESC;
-
GV$DATAFILE和GV$FREE_SPACE必须按INST_ID显式关联,否则会笛卡尔积 - 如果某
INST_ID缺失结果,说明对应实例已宕机或未注册进 CRS,不是查询问题 -
GV$BH查询量大时容易卡住,生产环境慎用全表扫描,建议加WHERE objd IN (SELECT data_object_id FROM dba_objects WHERE owner='SCOTT' AND object_type='TABLE')限定范围
真正影响性能的是 Cache Fusion 流量,不是“数据在哪”
很多用户纠结“这张表的数据在节点1还是节点2”,其实是个伪命题。RAC 的核心机制是 Cache Fusion:当节点2需要访问节点1 cache 里的 dirty block,会通过私网直接传输,而不是去磁盘读。所以关键指标不是数据物理位置,而是 gc cr block receive time、gc current block busy 这类等待事件。
- 查跨节点争用:用
SELECT * FROM gv$sysstat WHERE name LIKE 'gc%block%',重点关注gc cr blocks received和gc current blocks served的比值 - 高比例说明某节点频繁为其他节点提供 block,可能该节点承担了过多 index root block 或 sequence cache 请求
- 分区表没按业务键合理分区、序列没设
CACHE或NOORDER、没用 service 切分读写流量 —— 这些才是引发跨节点开销的根因,比查“数据在哪”重要得多
表空间使用率偏差超过15%、或者 GV$BH 显示某节点缓存占比持续高于70%,才值得深入调优。日常运维里,盯着 GV$WAITSTAT 和 AWR 中的 “Global Cache and Enqueue Services” 部分,比手动查分布有用得多。











