简单几招捕获Oracle递归SQL调用源头

简介:

作者介绍

蒋健云趣网络科技联合创始人,11g OCM,多年Oracle设计、管理及实施经验,精通数据库优化,Oracle CBO及并行原理,曾为多个行业的客户的 Oracle 系统实施小型机到 X86跨平台迁移和数据库优化服务。云趣鹰眼监控核心设计和开发者,资深Python Web开发者。

 

一、概述 

 

通常,DBA 确定通过 Oracle 的顶级活动会话图确定 Top SQL,有了 SQL 的执行会话信息和 SQL 文本,可以和开发人员确定 Top SQL 来自哪些应用模块的。有时候,Oracle DBA 需要自己确认 SQL 的来源,本文将演示如何使用 Oracle 提供丰富的跟踪功能,来确认递归 SQL 的调用者来源。

 

二、问题描述 

 

通过顶级会话页面,DBA 发现一个异常的 Top SQL,SQL ID 为c7452agj0s0t6,消耗了9%的数据库时间。

 

20161128100430811.jpg

 

通过 SQL 详情页面,可以确定 SQL c7452agj0s0t6 的用户名和模块,但是没有确定 SQL c7452agj0s0t6 是哪个客户机器造成的。

 

20161128100450144.jpg

 

从 SQL 的文本中,这是一个针对系统视图 V$ACTIVE_SESSION_HISTORY 的查询。

SELECT GROUP_TYPE, BUCKET_START, BUCKET_END, TM_GROUP_TYPE, TM_BUCKET_START,

      TM_BUCKET_END, SUM(TM_CPU_FIRST_BUCKET_VALUE) TM_CPU_FIRST_BUCKET_VALUE,

      SUM(TM_CPU_MIDDLE_BUCKETS_VALUE) TM_CPU_MIDDLE_BUCKETS_VALUE,

... 省略大量 SQL 文本

    FROM TABLE(SYS.GV$(CURSOR(

... 省略大量 SQL 文本       

    SELECT ASH0.*

    FROM V$ACTIVE_SESSION_HISTORY ASH0

... 省略大量 SQL 文本

 

通过 SQL 的活动会话信息,可以确定执行该 SQL 的进程为后台 PZ 进程,这些会话的 QC(query coordinator)不为空,也就是这是针对视图 V$ACTIVE_SESSION_HISTORY 的并行查询造成的。因为执行时间很短,并且执行此 SQL 的会话为短连接,无法查询到 QC 会话的来源。

 

20161128100505547.jpg

 

三、SQL ID 级别的跟踪分析 

 

为了确定 SQL c7452agj0s0t6 的来源,我们使用 Oracle 11g 中的新功能,对单个 SQL ID 打开10046事件跟踪,命令如下:

alter system set events 'sql_trace [sql:c7452agj0s0t6] wait=true,bind=true,plan_stat=all_executions,level=12';

 

通过以下查询确定 trace 文件的产生目录:

select value from v$diag_info where name='Default Trace File';

 

对最新生成的 PRDDB_oraxxx.trc 执行 grep c7452agj0s0t6,找到跟踪文件如下,可以确定该的客户端为 testapp。通过 dep=2,知道 SQL c7452agj0s0t6 为深度二级的递归 SQL,并不是用户直接提交的 SQL。我们依然不知道这个递归 SQL 具体由什么 SQL 调用的。

*** 2016-10-14 09:34:13.921

*** SESSION ID:(329.41269) 2016-10-14 09:34:13.921

*** CLIENT ID:() 2016-10-14 09:34:13.921

*** SERVICE NAME:(PRDDB) 2016-10-14 09:34:13.921

*** MODULE NAME:(python@testapp (TNS V1-V3)) 2016-10-14 09:34:13.921

*** ACTION NAME:() 2016-10-14 09:34:13.921

... 省略大量文本

=====================

PARSING IN CURSOR #139987897061528 len=11079 dep=2 uid=87 oct=3 lid=87 tim=1476408854404253 hv=3792438054 ad='21b01ba960' sqlid='c7452agj0s0t6'

 

关闭 SQL ID 跟踪的命令如下:

alter system set events 'sql_trace [sql:c7452agj0s0t6] off';

 

四、会话级别的跟踪分析 

 

为了确认什么 SQL 调用了 c7452agj0s0t6,我们需要在会话级别打开10046跟踪,因为执行 SQL c7452agj0s0t6 的会话是短连接,我们创建一个针对用户 APPUSER 的 logon 触发器,下次这个用户登录时会启动10046跟踪。

create or replace trigger sys.set_trace

after logon on database

when (user in ('APPUSER'))

declare

begin

execute immediate 'alter session set statistics_level=all';

execute immediate 'alter session set max_dump_file_size=unlimited';

execute immediate 'alter session set events ''10046 trace name context forever, level 12''';

end set_trace;

/

 

接着,在跟踪文件目录中找到最新生成的跟踪文件 PRDDB1_ora_10452.trc 包含 SQL ID c7452agj0s0t6。接着我们使用 orasrp 这个工具分析10046跟踪文件. orasrp 为 Oracle Session Resource Profiler,出自一位俄罗斯 DBA 的强大的10046分析工具,网址为:http://oracledba.ru/orasrp/

orasrp PRDDB1_ora_10452.trc PRDDB1_ora_10452.html

 

orasrp相对于 Oracle 自带的 tkprof,功能更加强大,其中一大优势是会生成会话的递归调用树。递归调用树(Session Call Graph)部分如下图,SQL hash value=3792438054 为 SQL c7452agj0s0t6,深度为2,顶级的 SQL hash value = 2036392974。

 

20161128100518405.jpg

 

顶级 SQL 文本如下,原来 SQL c7452agj0s0t6 是由 dbms_sqltune.report_sql_monitor 这个生成 SQL Monitor 报告的函数递归调用的。确定是前几天新部署的监控 job,在后台定时抓取和保存新生成的 SQL monitor 报告,但是执行过于频繁。解决的方法为降低后台 job 的执行频率,对每次抓取 SQL monitor 的执行时间提高限制。

select dbms_sqltune.report_sql_monitor(type=>:1, sql_id=>:2, sql_exec_id=>:3, report_level=>'ALL') monitor_report from dual;

 

确定问题来源之后,删除 logon 触发器,避免过多的跟踪文件产生:

drop trigger sys.set_trace;

 

五、总结 

 

本文演示了如果在 Oracle 中分别使用 SQL ID 和会话级别的10046跟踪,以确定递归 SQL 的调用源头来自 PL/SQL 函数 dbms_sqltune.report_sql_monitor。现实工作中,使用类似的方法,可以对 PL/SQL 代码性能,Oracle 解析时间过长等疑难杂症进行分析。对于 DBA 来说,使用 orasrp 对10046跟踪文件生成的递归调用树,也是研究应用负载特征的一个好手段。

原文发布时间为:2016-11-28

本文来自云栖社区合作伙伴DBAplus

相关文章
|
11天前
|
SQL 存储 Oracle
Oracle的PL/SQL定义变量和常量:数据的稳定与灵动
【4月更文挑战第19天】在Oracle PL/SQL中,变量和常量扮演着数据存储的关键角色。变量是可变的“魔术盒”,用于存储程序运行时的动态数据,通过`DECLARE`定义,可在循环和条件判断中体现其灵活性。常量则是不可变的“固定牌”,一旦设定值便保持不变,用`CONSTANT`声明,提供程序稳定性和易维护性。通过 `%TYPE`、`NOT NULL`等特性,可以更高效地管理和控制变量与常量,提升代码质量。善用两者,能优化PL/SQL程序的结构和性能。
|
11天前
|
SQL Oracle 安全
Oracle的PL/SQL游标异常处理:从“惊涛骇浪”到“风平浪静”
【4月更文挑战第19天】Oracle PL/SQL游标异常处理确保了在数据操作中遇到的问题得以优雅解决,如`NO_DATA_FOUND`或`TOO_MANY_ROWS`等异常。通过使用`EXCEPTION`块捕获并处理这些异常,开发者可以防止程序因游标问题而崩溃。例如,当查询无结果时,可以显示定制的错误信息而不是让程序终止。掌握游标异常处理是成为娴熟的Oracle数据管理员的关键,能保证在复杂的数据环境中稳健运行。
|
11天前
|
SQL Oracle 安全
Oracle的PL/SQL异常处理方法:守护数据之旅的“魔法盾”
【4月更文挑战第19天】Oracle PL/SQL的异常处理机制是保障数据安全的关键。通过预定义异常(如`NO_DATA_FOUND`)和自定义异常,开发者能优雅地管理错误。异常在子程序中抛出后会向上传播,直到被捕获,提供了一种集中处理错误的方式。理解和善用异常处理,如同手持“魔法盾”,确保程序在面对如除数为零、违反约束等挑战时,能有效保护数据的完整性和程序的稳定性。
|
11天前
|
SQL Oracle 关系型数据库
Oracle的PL/SQL中FOR语句循环游标的奇幻之旅
【4月更文挑战第19天】在Oracle PL/SQL中,FOR语句与游标结合,提供了一种简化数据遍历的高效方法。传统游标处理涉及多个步骤,而FOR循环游标自动处理细节,使代码更简洁、易读。通过示例展示了如何使用FOR循环游标遍历员工表并打印姓名和薪资,对比传统方式,FOR语句不仅简化代码,还因内部优化提升了执行效率。推荐开发者利用这一功能提高工作效率。
|
11天前
|
SQL Oracle 关系型数据库
Oracle的PL/SQL游标属性:数据的“导航仪”与“仪表盘”
【4月更文挑战第19天】Oracle PL/SQL游标属性如同车辆的导航仪和仪表盘,提供丰富信息和控制。 `%FOUND`和`%NOTFOUND`指示数据读取状态,`%ROWCOUNT`记录处理行数,`%ISOPEN`显示游标状态。还有`%BULK_ROWCOUNT`和`%BULK_EXCEPTIONS`增强处理灵活性。通过实例展示了如何在数据处理中利用这些属性监控和控制流程,提高效率和准确性。掌握游标属性是提升数据处理能力的关键。
|
11天前
|
SQL Oracle 安全
Oracle的PL/SQL循环语句:数据的“旋转木马”与“无限之旅”
【4月更文挑战第19天】Oracle PL/SQL中的循环语句(LOOP、EXIT WHEN、FOR、WHILE)是处理数据的关键工具,用于批量操作、报表生成和复杂业务逻辑。LOOP提供无限循环,可通过EXIT WHEN设定退出条件;FOR循环适用于固定次数迭代,WHILE循环基于条件判断执行。有效使用循环能提高效率,但需注意避免无限循环和优化大数据处理性能。掌握循环语句,将使数据处理更加高效和便捷。
|
11天前
|
SQL Oracle 关系型数据库
Oracle的PL/SQL条件控制:数据的“红绿灯”与“分岔路”
【4月更文挑战第19天】在Oracle PL/SQL中,IF语句与CASE语句扮演着数据流程控制的关键角色。IF语句如红绿灯,依据条件决定程序执行路径;ELSE和ELSIF提供多分支逻辑。CASE语句则是分岔路,按表达式值选择执行路径。这些条件控制语句在数据验证、错误处理和业务逻辑中不可或缺,通过巧妙运用能实现高效程序逻辑,保障数据正确流转,支持企业业务发展。理解并熟练掌握这些语句的使用是成为合格数据管理员的重要一环。
|
11天前
|
SQL Oracle 关系型数据库
Oracle的PL/SQL表达式:数据的魔法公式
【4月更文挑战第19天】探索Oracle PL/SQL表达式,体验数据的魔法公式。表达式结合常量、变量、运算符和函数,用于数据运算与转换。算术运算符处理数值计算,比较运算符执行数据比较,内置函数如TO_CHAR、ROUND和SUBSTR提供多样化操作。条件表达式如CASE和NULLIF实现灵活逻辑判断。广泛应用于SQL查询和PL/SQL程序,助你驾驭数据,揭示其背后的规律与秘密,成为数据魔法师。
|
19天前
|
SQL Oracle 关系型数据库
【Oracle】玩转Oracle数据库(一):装上去,飞起来!
【Oracle】玩转Oracle数据库(一):装上去,飞起来!
64 7
|
2月前
|
Oracle 关系型数据库 数据库
Oracle数据库基本概念理解(3)
Oracle数据库基本概念理解(3)
18 2

推荐镜像

更多