Oracle 11g中如何缓解Read by Other Session等待及处理数据热点和索引问题?
- 内容介绍
- 文章标签
- 相关推荐
本文共计921个文字,预计阅读时间需要4分钟。
相关专题
查出正在等待的 SQL 和对应对象
直接定位到问题源头最省时间。别先猜,先抓活的会话:
-
v$session中过滤event = 'read by other session',连带查出sql_id、p1(file#)、p2(block#) - 用
p1和p2去dba_extents查具体段:SELECT owner, segment_name, segment_type FROM dba_extents WHERE file_id = &file_id AND &block_id BETWEEN block_id AND block_id + blocks - 1 - 如果多个会话卡在同一个
segment_name上,基本可锁定是这张表或索引的热点问题
检查执行计划是否误走全表扫描或低效索引
90% 的 read by other session 都源于 SQL 计划错误,尤其是统计信息过期导致优化器选错路径:
- 用
dbms_xplan.display_cursor('&sql_id', null, 'ALLSTATS LAST')看真实执行路径,重点看是否出现大量TABLE ACCESS FULL或INDEX RANGE SCAN扫描了远超预期的块数 - 对比
PLAN_HASH_VALUE和历史 AWR 报告中的值,若不一致,说明计划已漂移 - 检查涉及表分区的统计信息:常见坑是某分区(如
part_202504)行数仍为 0,但实际已有几十万数据,DBMS_STATS.GATHER_TABLE_STATS必须指定partname参数重收集
确认是否真由热块引发,而非磁盘 I/O 拖累
read by other session 是“等别人读完”,背后一定有 db file sequential read 或 db file scattered read。但不能默认就是 SQL 问题:
- 查
v$system_event,看db file scattered read的平均等待时间是否 > 20ms —— 超过这个值,磁盘或存储层可能已成瓶颈 - 观察
read by other session的p3(class#):若集中为 1(data block)或 2(sort block),倾向热块;若分散且伴随高physical reads,优先排查 I/O 子系统 - RAC 环境下还要看
gc buffer busy acquire是否同步飙升 —— 可能是跨节点争用同一块,需结合gcs_lease和缓存融合策略评估
临时缓解与长期规避手段
改 SQL 或统计信息见效快,但有些场景必须从结构入手:
- 对高频访问的小表,考虑增大
INITRANS并调小PCTFREE,减少 ITL 争用引发的连锁等待 - 索引列存在严重数据倾斜(如状态字段只有 'A'/'B',但 99% 是 'A'),避免在该列建普通 B-Tree 索引,改用函数索引或分区裁剪
- 批量作业集中访问某张表的某个分区时,启用哈希分区(
HASH (partition_key))打散物理分布,比范围分区更能缓解单块争用 - 绝对不要依赖
buffer_cache大小来“掩盖”问题 —— 即便把db_cache_size加到 32GB,只要 SQL 还在扫 100 万块,read by other session就不会消失
真正难处理的是那种“看起来没毛病”的 SQL:执行计划正确、统计信息新鲜、I/O 响应正常,但几十个会话反复命中同一组索引叶块。这时候得去翻 X$BH 看 TCH(touch count),再结合应用逻辑判断是不是设计上就注定要串行化访问。
本文共计921个文字,预计阅读时间需要4分钟。
相关专题
查出正在等待的 SQL 和对应对象
直接定位到问题源头最省时间。别先猜,先抓活的会话:
-
v$session中过滤event = 'read by other session',连带查出sql_id、p1(file#)、p2(block#) - 用
p1和p2去dba_extents查具体段:SELECT owner, segment_name, segment_type FROM dba_extents WHERE file_id = &file_id AND &block_id BETWEEN block_id AND block_id + blocks - 1 - 如果多个会话卡在同一个
segment_name上,基本可锁定是这张表或索引的热点问题
检查执行计划是否误走全表扫描或低效索引
90% 的 read by other session 都源于 SQL 计划错误,尤其是统计信息过期导致优化器选错路径:
- 用
dbms_xplan.display_cursor('&sql_id', null, 'ALLSTATS LAST')看真实执行路径,重点看是否出现大量TABLE ACCESS FULL或INDEX RANGE SCAN扫描了远超预期的块数 - 对比
PLAN_HASH_VALUE和历史 AWR 报告中的值,若不一致,说明计划已漂移 - 检查涉及表分区的统计信息:常见坑是某分区(如
part_202504)行数仍为 0,但实际已有几十万数据,DBMS_STATS.GATHER_TABLE_STATS必须指定partname参数重收集
确认是否真由热块引发,而非磁盘 I/O 拖累
read by other session 是“等别人读完”,背后一定有 db file sequential read 或 db file scattered read。但不能默认就是 SQL 问题:
- 查
v$system_event,看db file scattered read的平均等待时间是否 > 20ms —— 超过这个值,磁盘或存储层可能已成瓶颈 - 观察
read by other session的p3(class#):若集中为 1(data block)或 2(sort block),倾向热块;若分散且伴随高physical reads,优先排查 I/O 子系统 - RAC 环境下还要看
gc buffer busy acquire是否同步飙升 —— 可能是跨节点争用同一块,需结合gcs_lease和缓存融合策略评估
临时缓解与长期规避手段
改 SQL 或统计信息见效快,但有些场景必须从结构入手:
- 对高频访问的小表,考虑增大
INITRANS并调小PCTFREE,减少 ITL 争用引发的连锁等待 - 索引列存在严重数据倾斜(如状态字段只有 'A'/'B',但 99% 是 'A'),避免在该列建普通 B-Tree 索引,改用函数索引或分区裁剪
- 批量作业集中访问某张表的某个分区时,启用哈希分区(
HASH (partition_key))打散物理分布,比范围分区更能缓解单块争用 - 绝对不要依赖
buffer_cache大小来“掩盖”问题 —— 即便把db_cache_size加到 32GB,只要 SQL 还在扫 100 万块,read by other session就不会消失
真正难处理的是那种“看起来没毛病”的 SQL:执行计划正确、统计信息新鲜、I/O 响应正常,但几十个会话反复命中同一组索引叶块。这时候得去翻 X$BH 看 TCH(touch count),再结合应用逻辑判断是不是设计上就注定要串行化访问。

