pl / sql dbms_scheduler挂起,如何进一步调试?

时间:2013-11-11 18:50:41

标签: oracle debugging plsql

我有一个由DBMS_SCHEDULER执行的PL / SQL块。它是在上周的某个时候开始的,现在应该已经完成​​,但事实并非如此。我正在尝试确定问题,但需要一些关于如何继续调试此问题的建议。以下是事实。

1)Oracle 11g

2)PL / SQL代码输出到日志表,我可以得到问题所在的一般区域,这就是我发现挂起的方式。我无法得到一个关于卡在哪里的行号。我不知道怎么回事。

3)V $ SESSION_LONGOPS表显示用户/架构仍在运行,但日期都是过去几天。从那时起它就没有动摇。

4)V $ SESSION_LONGOPS中的OPNAME在“收集表的索引统计”和“表扫描”之间拆分,用于一堆不同的表(第一个为8,第二个为8)。他们看起来是一个广泛的表格。对于每一行,SOFAR和TOTAL值彼此相等。 “Gather ...”行全为零,而“Table Scan”行不为零但相等。

5)如果我对V $ SESSION进行查询,我的工作是ACTIVE。

6)我正在处理的表上有一个锁,但我看不到我的架构中正在播放的其他会话。

7)CPU利用率非常低。

是否有可能更深入地查看正在执行的PL / SQL块?我可以在V $ SQL中找到完整的SQL,它向我展示了传入的原始块。我希望更深入地了解被编译的自定义过程(行号等)。

关于锁,我可以看到分配给我的表的V $ LOCKED_OBJECTS中的锁,是否有一个表将显示锁定的进程?我想找到死锁,如果有的话。

非常感谢任何建议,

MJ

2 个答案:

答案 0 :(得分:6)

如果不构建自己的检测,或启用调试或分析,则无法找到当前正在执行的行号。这似乎有点限制,但想象跟踪每个行号的性能影响。

大多数长时间运行的作业都在等待SQL,而不是PL / SQL。 (如果那不是真的,你还有其他问题。)有很多方法可以跟踪SQL语句。 V $ SESSION_LONGOPS可能很有用,但通常有更好的方法。如果有的话,最好的方法是使用Oracle Enterprise Manager。转到目标,然后转到Performance - >热门活动,您将看到过去一小时的系统活动和SQL语句图表。

例如(来自OEM Concepts指南): enter image description here

如果您没有安装OEM,或者没有访问权限,则还有其他几种跟踪SQL的方法。首先,您要确定哪些是相关的SQL语句。 这将告诉你现在正在运行什么,以及它运行了多长时间:

select elapsed_time/1000000 seconds, gv$sql.*
from gv$sql
where users_executing > 0
order by 1 desc;

如果你很幸运,这只是一个SQL语句需要很长时间。如果存在一系列小型SQL语句,则可能需要排除where users_executing > 0谓词并找到与您的应用程序相关的最昂贵的语句。

通常,SQL语句会很慢或停止,原因主要有三个:

  1. 等待资源。检查select * from dba_resumable;也许您的查询占用了太多的临时表空间,并且正在等待DBA添加更多内容。要么 也许你已经启用了并行排队,它正在等待更多的并行会话。 (我不确定这是否会出现在DBA_RESUMABLE中。)
  2. 等待锁定。检查select * from gv$session where final_blocking_session is not null;其中的任何行都可能存在问题。您通常想要 跟踪对象级别的锁定。更容易找到阻止你,而不是 阻止你。当一行或一个表被锁定时,你的 会话将等待事务,而不是行或对象。请注意,只有当两个会话以不同的顺序需要相同的资源时才会发生死锁 如果发生这种情况会有错误信息。
  3. 等待SQL执行。这显然是最困难的问题。现在该做什么没有简单的清单。通常我会先生成一个 活动报告,显示计划以及每个步骤需要多长时间:select dbms_sqltune.report_sql_monitor(sql_id => 'your sql id', type=>'active') from dual;。 该报告也适用于PL / SQL块,但它只会显示每个SQL占用的时间。然后由你决定如何让它运行得更好。

答案 1 :(得分:1)

  

是否有可能深入了解正在存在的PL / SQL块   执行?我可以在V $ SQL中找到完整的SQL,它显示了原始的   传入的块。我希望看到更深入的编译   调用的自定义过程(行号等)。

有很多观点,但这就是我的意思。

首先检查dba_scheduler_jobs:

select * from dba_scheduler_jobs
where owner = 'SOME_OWNER';

状态字段将显示正在运行,计划,停止等的哪个(一个或多个)。一旦找到您感兴趣的JOB,请检查job_type字段。如果它是STORED_PROCEDURE,您可以看到job_action中的哪个过程,或者是PLSQL_BLOCK时的匿名块。

如果JOB_TYPE是CHAIN,那么你需要多挖一点。连锁店将运行一系列工作/计划。首先,检查JOB_ACTION以查看链名称。将填充JOB_SUBNAME(如果链正在运行),显示正在执行的链中的当前步骤名称。您可以通过查看以下内容来检查链的规则(在何时运行):

select * from dba_scheduler_chain_rules
where chain_name = 'MY_CHAIN_NAME'

您还可以使用以下方法检查相关步骤:

select * from dba_scheduler_chain_steps
where chain_name = 'SOME_CHAIN_NAME'
and step_name = 'SOME_STEP_NAME'

此步骤视图将显示程序名称。该程序应与程序块或程序绑定:

select * from dba_scheduler_programs
where program_name = 'SOME_PROGRAM_NAME'

如果正在执行PLSQL_BLOCK,您将在PROGRAM_ACTION字段中找到确切的代码。

希望有所帮助。