原文地址:http://tech.e2sn.com/oracle-scripts-and-tools/session-snapper
原文作者:[Tanel Poder]
引言
Oracle Session Snapper v3相比较之前的版本(V2,V1)有很大的改进,除了获取各种 v$和 x$性能视图的快照和报告增量外,还从 v$session中抽取会话详细信息,这很像 Oracle 的 Active SESSION History 所做的统计采样(ASH 本质上只是一个 v$SESSION 的采样)。但是,使用 ASH 需要有额外的诊断程序包许可证,而查询 v $SESSION则不需要 (Snapper工具 就是做这样的事情),从3.52版本开始,Snapper 还支持 Oracle 9.2上的 ash- 样式的采样(在以前的版本中需要 Oracle 10g +)。
Oracle Session Snapper v3可以对v$SESSION 的 进行ASH 风格的采样, 现在可以报告 TOP 会话、 TOP wait 事件、 TOP SQL id、TOP pl/SQL 过程等。
尽管在 Oracle Session Snapper 中使用 ASH 风格的抽样,但它并不是 Oracle (独立授权的) ASH。这只是相同的概念,但不同的工具。Snapper 所做的只是使用普通的 PL/SQL 块对 v$SESSION 视图进行抽样,因此 Oracle 提供了免费的服务。
Snapper 是一个快速、简单的性能故障排除工具,适用于那些在数据库出现问题时亲自动手(并快速修复问题)的运维dba。Snapper 是一个灵活的第一轮性能故障排除工具,这是一个用于故障排除的入口工具,你可以在几秒钟内轻松地运行它,而不必立即采用诸如 SQL 跟踪等繁重的操作。
Snapper不会为你解决问题,它不提供任何智能性能建议,也不提供任何调优建议。它所做的就是展示信息。它将从 v$SESSTAT 等视图获取快照数据,并显示在快照期间某个会话的性能计数器增加了多少。Snapper v3还会显示在快照期间采集的活动 v$SESSION 样本的 TOP 报告,就像 ASH 那样
以下是关于 Snapper 的一些重要说明:
1、不在数据库中创建任何对象
2、只是一个匿名的 PL/SQL 块,可以动态地解析和编译
3、不会对数据库用户做任何更改
请注意,你现在正在阅读的这个文章并不是一个完整的系统性能故障排除指南,只是Session Snapper 工具的功能介绍。
使用Snapper工具
在下面示例中,假设你已经能够找出运行缓慢的会话(或作业运行缓慢)的 SID。假设它是140,那么你可以像这样运行 Snapper:
如果你对Snapper使用不清楚,下面介绍它的4个重要参数:
1、参数1(ash) 抽样类型
- 在 Snapper v3中,你可以使用“ ASH”进行活动会话历史记录样式的抽样
- 在早期版本和v3版本中,你可以使用“ STATS”来获取 v$SESSTAT 和其他性能计数器的快照
2、参数2(5) 快照的间隔周期
- 在示例中,Snapper每5秒统计,然后打印报告
3、参数3(1) 快照的统计次数
- 第一次诊断时,通常只使用一个快照/报表,但有时会使用更大的数字来获取多个快照和报表
4、参数4(140) 需要获取快照的会话SID
- 只指定一个会话,如140
- 指定多个会话,逗号隔开,如140,141,142
- 使用ALL指定所有会话
- 可以使用user=SYSTEM or program=sqlplus or module=HR
- 也可以使用子查询,类似select sid from v$session where username=‘SYSTEM’ and program not like ‘sqlplus%’"
Snapper工具的ASH模式使用
实例内单一会话运行的ASH模式
示例1
假设我们已经知道运行缓慢的会话SID 10,在 ASH 模式下运行 snapper,快照长度为5秒,一次在 SID 10上:
输出非常简单:
- Active% (%Thread,版本差异显示略有不同) 在采样的时间内,此会话花费的多少时间来相应执行输出行上列出的操作
- 100% 表明会话10一直在执行bu24rz6yy2vn1这个SQL
- enq: TX - row lock contention 代表会话在快照的5s内一直处于这个状态
由于 Snapper 的 ASH 功能(就像 ASH 本身一样)是通过定期采样 v$SESSION (类似于从其中获取快照)来工作的,所以它并不能捕获会话所做的每一件事。然而,它确实捕捉到了所有有意义的信息。
例如,我们不能完全确定这个会话是否真的100% 地执行了上面提到的操作,也许它只是忙于运行 SQLID,并且只有99% 的响应时间在等待该事件,并且在1% 的时间里执行了其他操作。Snapper 可能只是错过了另外1% 的采样,因为这个“其他”的事情发生得太快,在两个样本之间,所以它没有被捕获。然而,当一些事情发生的频率很低,而且发生的很快,以至于它甚至没有被记录在许多样本中的一个样本中,那么它就不能太重要了!如果某件事占用了50% 的响应时间,那么肯定会有一些样本(大约占总数的一半)显示“某件事”正在发生。
Snapper 报告输出的底部显示快照周期何时结束,在此期间完成了多少秒的采样以及完成了多少 v$SESSION 采样。上面我们看到 Snapper 在5秒钟内采集了45个 ASH 样本(每秒超过8个样本)。Snapper 的编写方式是,当快照周期很短时(最长可达10秒) ,采样速度非常快,但在快照周期较长时降低采样频率,以减少测量开销。在很长一段时间内,采样频率将是1赫兹,就像 ASH 一样每秒一次采样。
继续上面的示例,我们已经确定会话10一直在等待锁。我们现在可能想知道是谁在阻止我们,以及我们试图锁定的是哪种资源。在出现队列锁等待的情况下,等待事件附加细节列(Parameter2,3)将为我们提供关于我们试图锁定的对象/资源的附加信息(查看 v$LOCK 类型以了解其含义)。所以我们想要采集P2,P3从 v$SESSION 获得更多关于这个等待的详细信息。此外,在排队等待的情况下,我们可以示例 v $SESSION BLOCKING_SESSION 阻塞会话以查看哪个会话阻塞了我们。
因此,我不必依赖默认的 ASH TOP 活动分组,而是可以使用**ASH=**语法,请注意,并非所有的 v$SESSION 列在 Snapper 中都可用,但是最重要的是。我只需要指定我想取样的列的列表,列表之间用+分割。
现在我们可以看到更多的信息。阻塞的 SID 是140,我们正在等待的锁定对象的对象 ID 是1048579
上面的示例并没有真正显示 Snapper 的分析能力,因为会话被卡住,运行相同的语句,等待相同的事情。
示例2
另外一个例子:
显然,在这种情况下,会话并不是只等待单个等待事件,它运行的 SQL 与 TOP 会话活动报告中的所有 SQL ID 是相同的,但是在执行该 SQL 期间,会话有不同的等待事件,并且也花费了一些时间在 CPU 上。请注意,该会话的 CPU 使用率仅在 Snapper 运行期间为28% ,剩余响应时间的72% 都用于物理 IO 相关的等待事件(36% + 33% + 3%)。
因此,在对该会话的性能进行故障排除时,我已经知道100% 的响应时间(至少在 snapper 运行期间)用于使用 ID 执行 SQL3jbwa65aqmkvm 执行过程本身等待了72% 的时间用于 i/o。
示例3
在这种情况下,看起来在5秒快照运行期间执行了许多不同的语句。TOP SQL是一个至少30% 的时间处于活动状态(db file sequential read)。
由于报告了多个不同的语句,所有这些语句都占用了大量的响应时间——这都是因为 User i/o 等待事件,这可能是调查 IO 子系统问题的一种情况(突然之间所有语句都报告了 SQL i/o 等待)。
注意:还有一个更有重要的事情要看,Active% 为54% 。这意味着在采样期间这个会话只有54% 是活跃,因此,其余时间它是空闲的,通过网络,等待来自应用程序的下一个请求。如果你发现数据库会话只有很少一部分时间处于活动状态,那么对数据库中的任何内容进行优化都是没有意义的——你需要了解为什么应用程序向数据库发送新请求的速度不够快。
会话出现空闲的原因很多:
- 用户思考时间,用户请求频率不高。
- 应用思考时间。当应用程序服务器超载或者有一些错误的代码时,经常会发生这种情况。应用程序非常繁忙或陷入僵局,因此无法将请求发送到数据库并快速处理结果数据
- 网络延迟和吞吐量。把它放在最后,因为看用户和应用程序实际在做什么是有意义的,而不是立即假设问题一定是在网络中
请注意,正如我前面所说的,Snapper 是一个为你提供信息和性能数据的工具。它不会为你提供性能建议,你仍然需要遵循一个系统的方法进行故障排除和调优,Snapper 是支持它的工具。
所以,这就是所有的单个会话快照,但是,Snapper 可以做更多。
有时候你需要测量多个会话,有时候你甚至不知道 SIDs,有时候你需要看到整个实例活动。可以看下面的使用
实例内全部会话运行的ASH模式
使用 snapper 来度量所有会话的活动很容易,你只需指定all,不需要指定具体的sid
Active% 仍然显示一个会话的响应时间!如果两个会话的所有响应时间都在等待一个锁,那么你会看到200% 的等待时间。
如果我想分解有多少个会话正在等待某个事件,我可以添加sid 返回一个参数,如下所示,现在用于 TOP 报告的组由 SID、 event 和 wait _ class 完成:
SID 133是95% 的响应时间都在等待db file scattered read,剩下的5% db file sequential read . 在 IO 操作之间偶尔的 CPU 使用是如此短暂,以至于 Snapper 的 v$SESSION 抽样甚至没有看到它,换句话说,这个会话在 Snapper 运行期间没有显著地使用 CPU。
使用 Snapper 获取多个会话活动报告
如上所述,有时候,仅仅一个报告可能是不够的。你可能希望从多个不同的角度查看会话/实例活动数据(按不同的字段对 ASH 示例进行分组)。这就要使用Snapper 的ash1, ash2 及ash3 语法,你可以显示最多4 个ASH TOP 活动在一个 Snapper 运行。例如,假设我想通过 PL/SQL 包中的 object _ ID 和过程 ID 来分解会话活动,以查看是否有某个 PL/SQL 包导致了大部分工作(这些列可从 v$SESSION 中的10.2.0.3获得) 。
假设我想再加入一个报告,它向我展示了来自会话program, module 和action字段:
上面所有的东西都可以在 Snapper v3中找到。然而,这只是 Snapper 全部能力的一部分。有时仅仅知道 TOP sql_id 和 wait 事件是不够的。考虑一下这样的情况: 会话100% 使用 CPU,不等待任何事情,SQL 执行计划也没有明显的错误。这是你想知道session在做什么,这就到了 Oracle 的动态性能计数器发挥作用的地方——我主要谈论 v$SESSTAT 统计数据。
Snapper工具基于V$性能统计
自从版本V1之后,Snapper 就有了统计模式。这就是为什么我最初编写 Snapper,来帮助我进行性能故障排除,特别是在像 SQL 跟踪或者像 AWR/Statspack 这样的实例级性能工具没有显示任何有用信息的情况下。从 v3开始,Snapper 不会自动显示 v$SESSTAT 的统计数据,因为 Snapper 现在也被用作一个实例范围的故障排除工具(而且在实例中有数千个会话时,查询所有会话的 v$SESSTAT 可能会非常昂贵)。
因此,如果你想深入了解 v$SESSTAT 示例,你需要使用stats 参数进行统计, Snapper 从v$SESSTAT 和其他 v $视图的获取快照。也可以使用all(代表ash 和stats)
另外,你可以指定要捕获的统计类型,利用gather 选项
选项如下:
Session-level stats:
s - Session Statistics from gv$sesstat
t - Session Time model info from gv$sess_time_model
w - Session Wait statistics from gv$session_event and gv$session_wait
Instance-level stats:
l - instance Latch get statistics ( gets + immediate_gets )
e - instance Enqueue lock get statistics
b - buffer get Where statistics – useful in versions up to 10.2.x
a - All above
如果启用了stats ,但是没有使用gather ,那么仅仅在会话级统计(s,t,w)
在实例级运行Snapper工具
例如,我从所有会话中获取 ash session 活动快照,但是我也要求 Snapper 收集 Time Model Stats (t)和 v $SESSTAT Stats (s) ,但是只包括 Time Model Stats (tinclude) ,其名称中包含字符串% CPU% ,只包含 v $SESSTAT (sinclude) ,其中包含单词% parse% :
在上面输出的上半部分,可以 Snapper 的统计模式中会话133,每秒2.25千硬解析(这是一个很大的!).我可以使用 v$SESSTAT 中提供的任何其他统计数据(在 Oracle 11.2中,每个会话有600多个不同的统计数据)。例如,如果我在sinclude 参数中使用"redo size",我将很容易看到哪个会话生成最多的重做日志。
另一件要注意的事情是,下面的 ASH 部分说有 CPU 活动值为单个会话响应时间的105% (这意味着必须有一个以上的会话使用该 CPU) ,上面的时间模型统计(stats type = TIME)根本没有报告显著的 DB CPU 使用情况。这里的问题是度量粒度。时间模型统计数据仅在数据库调用结束时在v$视图中更新,但是如果数据库调用是长时间运行的(如我的测试案例) ,那么 V$SESS_TIME_MODEL中的统计数据默认情况下大约每5秒更新一次。由于我的 Snapper 运行时间很短(5秒) ,脚本显然在V$SESS_TIME_MODE更新发生在长时间运行的数据库调用会话之前就完成了。如果你用更长的采样时间运行 snapper,比如60秒,你应该看到所有时间模型的统计数据。
到目前为止,我们已经介绍了如何在一个会话或整个实例上运行 snapper。有时候,你需要监视特定用户、服务或程序的所有会话。这在 Snapper 中也是可以的
在会话级运行Snapper工具
从 v3开始,Snapper 有方便的方法来指定user, application, service等信息。例如,你可以直接编写 user = ,而不是将第4个参数指定为 SID。
由于上面指定的参数(ash 和 ash1) ,我们得到了同一个会话活动数据的不同细分,我们只测量了属于用户 SOE 的会话。
可以指定其他参数:
- username (same as user)
- sid
- spid (same as pid and ospid)
- program
- machine
- osuser
- module
- action
- client_id
但是,你不能将这些参数组合成任何 AND 或 OR 条件,你只能使用上述方便的语法一次传递一个参数。
然而,如果你想要非常精确地知道哪些会话 Snapper 监视器(如果你想要添加多个和/或条件来选择感兴趣的会话) ,那么你可以用老方法来选择会话
你可以在双引号之间编写任何子查询作为 SID 参数,只要它适合于命令行并返回一个带有 SID 列表的数字列即可
下载Snapper工具
可以通过以下地址下载
https://github.com/tanelpoder/tpt-oracle/blob/master/snapper.sql
更多文章参考
你可以在我的博客上看到所有与 snapper 相关的文章:
反馈
我很多年前就写了初版的 Snapper,但我仍然不清楚有多少人真正在使用它,以及他们是如何使用它的,所以如果 Snapper 过去曾经帮助过你(或者现在正在帮助你) ,那么请给我发一封电子邮件,告诉我你是如何使用它的