高频db file scattered read会话需聚合统计ASH中最近5分钟≥10次的WAITING状态User I/O等待,结合program、current_obj#、sql_id定位大表扫描及可疑SQL,并排除系统任务、小表、已知业务等合理场景,确认后立即kill并审计权限。

查 v$active_session_history 中高频 db file scattered read 的会话
全表扫描在 ASH 里最典型的信号是大量出现 db file scattered read 等待事件,且 session_state = 'WAITING'、wait_class = 'User I/O'。这不是偶尔一两次,而是连续多秒(甚至跨多个采样点)重复出现。
执行以下查询,聚焦最近 5 分钟内该等待事件出现 ≥ 10 次的活跃会话:
SELECT session_id, session_serial#, username, program, COUNT(*) cnt FROM v$active_session_history WHERE sample_time > SYSDATE - 5/1440 AND event = 'db file scattered read' GROUP BY session_id, session_serial#, username, program HAVING COUNT(*) >= 10 ORDER BY cnt DESC;
- 注意:不要只看单条记录——
v$active_session_history是每秒采样,恶意全表扫描通常持续数秒以上,所以必须聚合统计 -
program字段常暴露来源:比如sqlplus@host、jdbc thin client、或异常的后台程序名(如未授权脚本) - 若
username为空但program可疑,要结合machine和terminal追溯客户端 IP
关联 current_obj# 定位被扫的表和执行 SQL
拿到高频会话 ID 后,进一步查它正在扫哪张表、跑什么 SQL。关键字段是 current_obj#(当前操作对象 ID)和 sql_id(如果有):
SELECT DISTINCT sql_id, current_obj#, o.object_name, o.object_type, event, p1text, p1, p2text, p2 FROM v$active_session_history ash JOIN dba_objects o ON ash.current_obj# = o.object_id WHERE session_id = &sid AND sample_time > SYSDATE - 2/1440 AND event = 'db file scattered read';
-
current_obj#对应的是实际被访问的表(不是索引),可直接确认是否为大表或敏感表 - 若
sql_id为空,说明可能是匿名 PL/SQL 块、硬解析失败的 SQL,或用了绑定变量但未缓存;此时重点看program+machine组合 - P1/P2 参数值本身不重要,但
p1text = 'file#'、p2text = 'block#'能佐证是物理读行为,排除内存中完成的逻辑读
排除误报:区分“合理全表扫描”和“可疑行为”
不是所有 db file scattered read 都代表恶意操作。以下情况属于正常范畴,需快速过滤:
- 系统维护任务:如
ora_mmon_*或ora_mmnl_*进程在做 AWR 快照或统计刷新,它们扫的是WRH$或WRI$系统表,username为空、program固定可识别 - 小表扫描:若
current_obj#对应的表num_rows ,且 <code>blocks ,优化器选全表扫描是合理的 - 已知业务 SQL:比如报表类应用明确配置了
/*+ FULL(t) */,且该 SQL 在dba_hist_sqlstat中有稳定历史执行记录 - 并行查询(
px qcsid非空):这是主动启用的并行全表扫描,不是失控行为
真正可疑的是:普通应用用户、非系统程序、扫描大表(>100 万行)、无对应历史 SQL_ID、且发生在业务低峰期。
实时拦截与后续动作
确认是恶意会话后,不能只查不拦。Oracle 不提供“自动 kill 全表扫描会话”的开关,必须人工干预:
- 先用
SELECT sql_text FROM v$sql WHERE sql_id = '&sql_id';看完整语句,确认无业务上下文再行动 - 用
ALTER SYSTEM KILL SESSION '&sid,&serial#';终止,注意加IMMEDIATE避免等待事务回滚完成 - 立刻查
dba_audit_trail或统一审计策略(如果启用),确认该会话登录时间、客户端 IP、是否绕过应用层直连 - 检查该用户是否有
SELECT ANY TABLE或过度授予的权限——这才是根源,比 kill 会话更重要
ASH 数据只保留内存中的最近 1 小时左右(默认),一旦会话结束又没及时抓取,就无法回溯。所以发现苗头必须秒级响应,不能等报告生成。


















