导读:本期聚焦于越南程序员创作的《如何利用Oracle ASH活动会话历史快速定位数据库性能瓶颈?》,敬请观看详情。数据库突然变慢却找不到原因,往往是因为缺少会话级的细粒度观测手段。Oracle ASH(活动会话历史)以每秒采样的方式记录处于活跃状态的会话信息,包含SQL ID、等待事件、阻塞会话、执行计划等字段。与AWR报告偏向宏观不同,ASH能还原故障时间窗内每一个被卡住的会话轨迹。通过查询V$ACTIVE_SESSION_HISTORY视图,可以按等待事件排序找出消耗时间最长的环节,或根据SESSION_ID追溯锁等待链条。掌握ASH的采样机制与核心字段含义,能帮助运维人员在分钟级定位到某条慢SQL或行锁争用,而不必等完整AWR生成后再排查。

Oracle数据库在日常运行中经常会出现间歇性性能下降,这类问题往往持续时间短、发生突然,传统的快照级报告很难捕捉到现场。ASH(Active Session History,活动会话历史)作为Oracle内置的轻量级诊断组件,以固定的时间间隔对数据库中处于非空闲状态的会话进行采样,并将这些会话的活动细节写入内存中的环形缓冲区。当系统出现响应变慢、CPU飙升或者锁等待加剧时,只要故障窗口落在ASH采样保留期内,我们就可以通过分析这些样本还原出当时每一个活跃会话在做什么、等什么以及被谁阻塞。

如何利用Oracle ASH活动会话历史快速定位数据库性能瓶颈?

ASH的采样机制与核心数据结构

ASH的采样频率默认是每秒一次,由后台进程MMNL负责将活跃会话的信息写入SGA中的ASH缓冲区。所谓活跃会话,是指那些当前正在消耗CPU或者处于某种等待事件(如IO等待、锁等待、网络等待)中的会话,空闲会话不会被记录。这种只记录活跃会话的设计,既控制了数据量,又保证了在性能问题发生时能够拿到最有价值的现场信息。ASH缓冲区是一个固定大小的内存区域,当写满之后新的采样会覆盖最旧的记录,因此在默认配置下,ASH在SGA中通常只能保留几分钟到几十分钟的数据,具体时长取决于数据库负载和缓冲区大小。

除了内存中的V$ACTIVE_SESSION_HISTORY视图,Oracle还会定期将ASH缓冲区中的数据刷入磁盘,形成DBA_HIST_ACTIVE_SESS_HISTORY表,这部分数据会保留更长时间并作为AWR报告的数据源之一。我们在做实时诊断时主要查询V$ACTIVE_SESSION_HISTORY,它包含的字段非常丰富,例如SAMPLE_TIME采样时间、SESSION_ID会话编号、SQL_ID当前执行的SQL标识、EVENT等待事件名称、WAIT_CLASS等待类别、BLOCKING_SESSION阻塞者会话、TOP_LEVEL_SQL_ID以及SQL_PLAN_HASH_VALUE执行计划哈希值等。理解这些字段是后续分析的基础,特别是EVENT和BLOCKING_SESSION,前者告诉我们会话卡在哪里,后者让我们看清锁等待的源头。

与AWR相比,ASH更偏向于微观和会话级。AWR每小时生成一次快照,汇总的是整体资源消耗,容易掩盖短时间突发问题;而ASH每秒采样,能精确定位到故障发生的那几十秒里,是哪条SQL、哪个模块、哪种等待事件在拖累系统。在真实运维中,如果接到业务反馈某报表查询在上午十点零三分突然卡住,直接查那个时间点的ASH数据,往往比等下一个AWR快照高效得多。

基于等待事件与SQL的实用查询方法

最常见的ASH分析思路是按等待事件聚合,找出采样次数最多、也就是会话累计等待时间最长的事件类别。比如系统响应慢,我们怀疑是IO瓶颈,就可以统计某时间段内各类等待事件的样本分布。下面这段SQL演示了如何查询最近十五分钟内,各等待事件对应的活跃会话采样数:

SELECT
    NVL(event, 'ON_CPU') AS wait_event,
    COUNT(*) AS sample_count,
    ROUND(COUNT(*) * 100.0 / SUM(COUNT(*)) OVER (), 2) AS pct
FROM v$active_session_history
WHERE sample_time >= SYSDATE - INTERVAL '15' MINUTE
GROUP BY event
ORDER BY sample_count DESC;

如果查询结果显示ON_CPU占比极高,说明大量会话在烧CPU,可能是糟糕的SQL做了全表扫描或大量计算;如果显示db file sequential read很多,则指向索引扫描类的IO等待;若是enq: TX - row lock contention突出,那就是典型的应用层行锁争用。拿到等待事件之后,下一步通常是关联SQL_ID,看看是哪些语句引发了这些等待。我们可以把上面结果中的热点事件与SQL_ID组合查询,定位到具体的慢SQL文本和执行计划。

另一种非常实用的分析是锁等待链追踪。当应用反馈更新操作卡死时,利用BLOCKING_SESSION字段可以快速画出谁阻塞了谁。以下示例找出当前被阻塞会话及其阻塞源,并附带它们正在执行的SQL:

SELECT
    h.session_id AS blocked_sid,
    h.blocking_session AS blocker_sid,
    h.event AS wait_event,
    h.sql_id AS blocked_sql,
    b.sql_id AS blocker_sql
FROM v$active_session_history h
LEFT JOIN v$active_session_history b
    ON h.blocking_session = b.session_id
    AND h.sample_time = b.sample_time
WHERE h.blocking_session IS NOT NULL
    AND h.sample_time >= SYSDATE - INTERVAL '10' MINUTE
ORDER BY h.sample_time DESC;

这类查询能直接暴露出阻塞链条,比如某个会话做了未提交的事务持有行锁,导致后续几十个会话堆积在enq: TX等待上。定位到阻塞源SQL_ID后,结合DBA_OBJECTS和应用日志,就能明确是哪张表、哪个业务逻辑忘记提交。相比盲目杀会话,用ASH数据说话可以最小化误杀风险。

结合AWR与日常监控的落地建议

虽然ASH本身数据保留短,但通过与AWR的协同可以形成长短结合的诊断体系。在日常监控中,我们可以配置脚本每五分钟抓取一次V$ACTIVE_SESSION_HISTORY的异常等待,一旦某种等待事件占比超过阈值就告警。对于历史疑难问题,则从DBA_HIST_ACTIVE_SESS_HISTORY中按更长周期回放,比如对比一周内每天上午高峰时段的TOP SQL变化。这种用法不需要在业务侧埋点,完全基于数据库自带能力,实施成本很低。

在落地时还要注意权限与开销问题。查询V$ACTIVE_SESSION_HISTORY需要SELECT_CATALOG_ROLE或相应系统权限,生产环境应分配给监控账号而非业务账号。ASH采样本身对数据库性能影响极小,但在高并发场景下如果频繁做大量GROUP BY查询,也会产生额外解析和CPU消耗,因此建议将分析SQL固化成视图或定时任务,避免在故障高发期由多人同时跑复杂ASH查询。另外,对于使用了多租户架构的Oracle环境,CDB和PDB级别的ASH视图名称略有差异,排查时要确认当前容器,防止查错数据源。

从架构思考的角度看,ASH本质上提供了一种低成本的分布式追踪思路:把每个会话当作一个请求链路节点,每秒打点。我们在设计自有系统监控时也可以借鉴,对关键线程或协程做轻量采样,记录其状态与阻塞对象,在出现毛刺时迅速回放。当团队逐渐积累起ASH分析的经验模板,例如常见的锁等待链、硬解析风暴、缓冲忙等待等模式,定位线上问题的平均耗时将从小时级压缩到几分钟,这对保障核心交易系统的稳定性具有实际价值。

OracleASH活动会话历史修改时间:2026-08-16 13:18:39

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。