ash不能监控长事务进度,因其仅采样会话瞬时状态,不反映回滚块处理、完成百分比或剩余时间;真实进度需查v$fast_start_transactions、x$ktuxe结合v$transaction定位。

ASH 本身不记录长事务“正在回滚”或“提交中”的状态
直接查 V$ACTIVE_SESSION_HISTORY 找不到事务进度、剩余时间、undo块处理量——它只捕获「当前在CPU上运行」或「正在等某个事件」的会话快照。长事务若处于静默等待(比如SMON在后台回滚)、或已提交但会话未断开,event 字段常为空或显示 SQL*Net message from client,根本看不出和事务有关。
真正要定位长事务来源,得先确认:它是否还在活跃阻塞别人?还是已经结束、只是会话没释放?
- 如果
blocking_session非空,且对应会话的status = 'ACTIVE'、sql_id有值,优先顺着这个会话查v$transaction - 如果
blocking_session为空,但该会话的used_ublk在持续增长(查v$session关联v$transaction),说明它仍在生成 undo,大概率是未提交的长事务 - 别信
MODULE和ACTION:应用层设置可能残留、未更新,ACTION IS NULL很常见,不能据此排除某服务
用 ASH 辅助圈定可疑会话范围(过去1分钟)
虽然 ASH 不反映事务内部状态,但它能快速暴露“谁最近频繁惹事”。重点不是看单条记录,而是看模式:
- 执行
SELECT session_id, blocking_session, event, COUNT(*) FROM v$active_session_history WHERE sample_time > SYSDATE - 1/1440 GROUP BY session_id, blocking_session, event ORDER BY COUNT(*) DESC - 关注
event IN ('enq: TX - row lock contention', 'library cache lock', 'cursor: pin S wait on X')的高频会话 - 同一
session_id连续出现blocking_session = 0但event = 'enq: TX - row lock contention',说明它自己就是持锁者(没被别人堵,但它堵了别人)
关联 v$transaction 定位真实事务发起者
拿到可疑 session_id 后,必须跳到 v$transaction 查底层事务信息,因为一个会话可能开启多个事务,而 ASH 只记录会话级采样:
- 用
SELECT t.addr, t.xidusn, t.xidslot, t.xidsqn, t.used_ublk, t.start_time FROM v$transaction t JOIN v$session s ON t.ses_addr = s.saddr WHERE s.sid = &sid -
used_ublk是关键:>5000 基本可判定为长事务;连续两次查询差值大,说明仍在活跃修改 -
start_time要结合系统时区确认,别直接比对SYSDATE,Oracle 默认存的是数据库时区时间 - 再用
t.addr反查v$session拿username、program、machine,比单纯看MODULE更可靠
为什么不能只靠 ASH 的 sql_id 定位长事务源头
sql_id 在 ASH 里常为空或指向一条简单 SELECT,因为长事务的“源头 SQL”往往早已执行完,后续只是等待提交或被回滚——SMON 回滚时不走用户 SQL 执行链,也不产生新 sql_id。
典型场景:
- 一个
UPDATE /*+ APPEND */执行完后卡住,ASH 里看到的是event = 'log file sync'或空等待,sql_id已失效 - 手动
ROLLBACK开始后,会话不再执行任何 SQL,ASH 中只剩SQL*Net message from client,但v$transaction.used_ublk仍在下降 - 崩溃恢复触发的快速启动(fast-start),事务由 SMON 驱动,
v$fast_start_transactions才有undoblocksdone,ASH 里完全无迹可寻
真正源头永远在 v$transaction + v$session 的组合里,ASH 只是帮你从一堆活跃会话中快速筛出“最可能有问题的那个”。











