ash无法直接查客户端ip,因其不含client_ip字段;需通过v$session_connect_info、监听日志或应用层埋点(如dbms_session.set_identifier)关联真实ip,并用session_id+session_serial#反向匹配ash记录。
直接查 v$active_session_history 无法拿到客户端真实ip——这个视图压根没有 client_ip 字段,硬查会返回空或报错。
为什么ASH里查不到IP?
Oracle 的 V$ACTIVE_SESSION_HISTORY 记录的是会话在 CPU 或等待事件上的“行为快照”,不采集 TCP 层源地址。它只存 SESSION_ID、SESSION_SERIAL#、SQL_ID、EVENT 等执行上下文,不存网络层信息。
-
V$SESSION中的MACHINE或OSUSER在共享服务器模式下可能失真,不能当 IP 用 -
CLIENT_IDENTIFIER字段为空?说明应用没调用DBMS_SESSION.SET_IDENTIFIER主动设值 - 监听日志(
$ORACLE_HOME/network/log/listener.log)里才有HOST=192.168.x.x这类原始记录,但默认不开启详细日志
怎么把ASH会话和真实IP关联起来?
必须走交叉验证路径:先从操作系统或监听器拿到 IP → 关联到 V$SESSION → 再反向匹配 V$ACTIVE_SESSION_HISTORY 中的同一会话。
- 在数据库服务器上跑:
netstat -an | grep :1521 | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -nr | head -10,快速定位连接最多的客户端IP - 查
V$SESSION中对应 IP 的会话:SELECT sid, serial#, username, program, machine FROM v$session WHERE machine LIKE '%192.168.0.101%'(注意:machine 不等于 IP,但常含主机名或部分IP) - 用拿到的
SID和SERIAL#去查 ASH:SELECT sql_id, event, COUNT(*) FROM v$active_session_history WHERE session_id = 123 AND session_serial# = 4567 AND sample_time > SYSDATE - 1/24 GROUP BY sql_id, event - 如果应用可控,强制要求 Java/Python 连接时设置
clientinfo:conn.setClientInfo("CLIENT_IP", "192.168.0.101"),这样V$SESSION.CLIENT_INFO和 ASH 的CLIENT_ID就能对上
查最近恶意请求总失败?时间范围写错了
执行 SELECT * FROM v$active_session_history WHERE sample_time > SYSDATE - 1/1440 返回空,大概率不是没数据,而是采样点没对上或已被刷出内存。
- ASH 默认每秒采样一次,但只保留在 SGA 中约 30–60 分钟(取决于
_ash_disk_write_threshold和 SGA 大小),查“最近1分钟”不如查“最近5分钟”稳妥 - 改用:
SAMPLE_TIME > SYSDATE - 5/1440(即最近5分钟),再加ORDER BY SAMPLE_TIME DESC看时间戳是否连续 - 别依赖纯时间过滤,优先用已知 IP 关联出的
SESSION_ID+SESSION_SERIAL#直接捞 ASH 记录,更准、更快、不受采样窗口影响
真正难的不是查到 IP,而是确认那个 IP 后面到底跑的是什么程序——netstat -tulpn 在应用服务器上看到的 6666/java 才是关键线索,ASH 只负责告诉你这个 java 进程正在执行哪条 SQL、卡在哪类等待上。











