v$access易误判因它仅记录会话对过程的访问关系而非实时执行状态,即使过程未运行、休眠或挂起,只要被引用或持有句柄即会显示。
直接查 v$access 是最贴近“谁在调用哪个过程”的方式,但结果不等于“正在执行中”——它只表示该过程被某个会话打开并持有句柄,哪怕当前卡在 pl/sql 循环里没发 sql,也可能不显示。
为什么 V$ACCESS 的结果容易误判
V$ACCESS 记录的是会话对数据库对象的“访问关系”,不是实时执行栈。只要一个会话执行了 CALL your_proc 或在 PL/SQL 块里引用了该过程(哪怕只是声明、未调用),就可能出现在这个视图里。
- 它不区分“刚进入”、“正在运行”还是“已挂起等待锁”
-
STATUS = 'ACTIVE'来自关联的V$SESSION,但V$SESSION.STATUS = 'ACTIVE'本身只表示会话最近有活动,不一定正在跑你的过程 - 如果过程内部调用了 DBMS_LOCK.SLEEP 或等待 DB Link 远程响应,
V$ACCESS仍会保留记录,但实际已停滞
V$ACCESS + V$SESSION 关联查询的实际写法
必须显式 JOIN 并过滤状态和类型,否则容易漏掉或误抓:
SELECT a.sid, a.owner, a.object, a.type,
s.username, s.status, s.event, s.sql_id
FROM v$access a
JOIN v$session s ON a.sid = s.sid
WHERE a.type = 'PROCEDURE'
AND s.status = 'ACTIVE'
AND a.object = 'YOUR_PROC_NAME'
AND a.owner = 'YOUR_SCHEMA';
-
a.object和a.owner必须精确匹配,大小写敏感(除非用双引号定义) -
s.event是关键线索:若为PL/SQL lock timer、SQL*Net message from client,说明过程其实没在跑;若为db file sequential read或enq: TX - row lock contention,才更可能是真正在执行 -
s.sql_id可进一步去查v$sql看当前执行的语句是否属于该过程逻辑
比 V$ACCESS 更可靠的替代方案
单靠 V$ACCESS 容易给出“假阳性”。真正要确认“此刻正在 CPU/IO 上跑”,应优先组合以下视图:
- 查
v$db_object_cache:看locks > 0 AND pins > 0,说明过程代码正被加载且被会话固定使用 —— 这比V$ACCESS更接近“运行中”语义 - 查
v$session_longops:过滤opname LIKE '%PL/SQL%'或target_desc LIKE '%YOUR_PROC_NAME%',能反映长时间操作的真实进度 - 查
v$session的plsql_entry字段(Oracle 10g+):SELECT plsql_entry FROM v$session WHERE sid = ?,可直接看到当前 PL/SQL 调用栈顶层
真正难判断的,是那些没做任何 SQL 操作、纯逻辑计算或休眠的存储过程 —— 它们不会在 v$sql 或 v$session_longops 留下痕迹,V$ACCESS 却还挂着。这种情况下,唯一办法是提前在过程里用 DBMS_APPLICATION_INFO.SET_ACTION 打标记,再查 v$session.action。











