备库长连接监控不能直接查v$session因dg备库在read only with apply或mount状态下,v$session中多为mrp/rfs等后台进程,需筛选username非空、type='user'、last_call_et>1800且program不匹配'ora_%'的会话。
备库长连接sql监控为什么不能直接查 v$session
因为dg备库在 read only with apply 或 mount 状态下,大部分会话由mrp(managed recovery process)或rfs(remote file server)进程驱动,不是用户发起的常规连接;你看到的 v$session 中 username 为空、program 为 ora_mrp0_* 或 ora_rfs_* 的会话,本质是后台恢复进程,不是“应用长连接”。真正需要关注的,是那些以真实业务用户身份连入备库、又长期空闲的会话——它们只会在备库开启 read only(未启用实时应用)时出现。
如何识别备库上可疑的用户长连接
执行以下查询,重点筛出非后台、非空用户名、且空闲超30分钟的会话:
SELECT SID, SERIAL#, USERNAME, STATUS, LOGON_TIME, LAST_CALL_ET, MODULE, CLIENT_IDENTIFIER, SQL_ID, EVENT FROM V$SESSION WHERE STATUS = 'INACTIVE' AND LAST_CALL_ET > 1800 AND USERNAME IS NOT NULL AND TYPE = 'USER' AND PROGRAM NOT LIKE 'ora_%';
-
LAST_CALL_ET > 1800是硬指标:单位秒,表示“上一次调用结束至今”,不是连接时长,但结合LOGON_TIME可算出真实存活时间 - 必须排除
PROGRAM LIKE 'ora_%',否则会混入MRP/RFS/LGWR等后台进程 - 若
EVENT是'SQL*Net message from client',基本确认客户端已断开逻辑交互,但TCP连接未关闭 - 常见陷阱:某些JDBC连接池在备库只读模式下仍维持连接,
MODULE固定为'JDBC Thin Client',CLIENT_IDENTIFIER为空或恒定
为什么不能只靠 ASH 查这些会话的行为
V$ACTIVE_SESSION_HISTORY 每秒采样一次,且**只记录活动会话**(即正在执行SQL、等待事件或CPU运行中)。一旦用户会话进入 INACTIVE 状态,它就从ASH中彻底消失——哪怕这个连接已经挂了2小时、占着PROCESSES配额、甚至因未提交而锁住行。所以:
- 单独查
V$ACTIVE_SESSION_HISTORY会漏掉所有“假活”长连接 - 只有当你怀疑某个已识别的长连接曾偶发执行过重负载SQL(比如夜间报表),才用它的
SESSION_ID和SESSION_SERIAL#去反查ASH:SELECT SAMPLE_TIME, SQL_ID, EVENT, TIME_WAITED FROM V$ACTIVE_SESSION_HISTORY WHERE SESSION_ID = <sid> AND SESSION_SERIAL# = <serial></serial></sid> - 注意:ASH历史最多保留1小时(默认),超出部分进
DBA_HIST_ACTIVE_SESS_HISTORY,需额外权限和AWR快照支持
监控脚本里必须避开的DG状态陷阱
很多通用监控脚本会无差别查 V$SESSION,但在DG备库上容易误报:
- 在
MOUNT状态下,V$DATABASE.OPEN_MODE是'MOUNT',但此时根本不会有用户会话,查到的全是后台进程——直接过滤TYPE = 'USER'就能避开 - 在
READ ONLY WITH APPLY下,用户无法执行DML,但可以连入并执行查询;此时若发现STATUS = 'ACTIVE'且SQL_ID长期不更新,要立刻看EVENT:如果是'log file sync'或'db file sequential read',说明真在干活;如果是'SQL*Net message from client',大概率是连接池没回收 - 别依赖
V$DATAGUARD_STATS的apply lag来判断会话是否“健康”——它反映的是日志应用延迟,和用户连接生命周期无关
真正关键的交叉验证点只有一个:用 LOGON_TIME 算出连接真实时长,再结合 LAST_CALL_ET 判断它是否“活着但不动”。其他视图都是辅助,不能替代这个时间轴判断。











