3

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

1) 甲骨文 11g

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

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

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

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

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

7) CPU 利用率很低。

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

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

非常感谢任何建议,

4

2 回答 2

6

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

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

例如(来自 OEM 概念指南): 在此处输入图像描述

如果您没有安装 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 花费的时间。然后由你来决定如何让它运行得更好。
于 2013-11-11T19:23:37.473 回答
1

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

那里有很多观点,但这就是我所做的。

您首先检查 dba_scheduler_jobs:

select * from dba_scheduler_jobs
where owner = 'SOME_OWNER';

state 字段将显示哪些(s)正在运行、已调度、已停止等。找到您感兴趣的 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 字段中找到确切的代码。

希望有帮助。

于 2013-11-11T19:44:57.867 回答