PL/SQL - 如何检查是不是正在使用包/过程/函数?

Posted

技术标签:

【中文标题】PL/SQL - 如何检查是不是正在使用包/过程/函数?【英文标题】:PL/SQL - How can I check if a Package / Procedure / Function is being used?PL/SQL - 如何检查是否正在使用包/过程/函数? 【发布时间】:2015-04-02 17:09:17 【问题描述】:

你好,谁看到这个。 首先,我对 PL/SQL 的了解对于外行来说非常基础。我可以阅读代码、进行查询并使用 PL/SQL Developer 进行研究。这就是我需要做的。

我只需要知道是否正在使用包/过程/功能和/或上次使用它的时间。有没有办法通过 PL/SQL Developer 的查询或功能看到它?

旁注:我发现了下面的问题,但它不符合我的需求/没有完全理解遮阳篷的用途: How can you tell if a PL/SQL Package, Procedure, or Function is being used?

【问题讨论】:

您所说的“二手”是什么意思?你的意思是它是否被任何其他对象/函数/过程/等引用。还是您的意思是它当前是否正在执行/运行? 嗨,米娜,感谢您的回复。我的意思是它当前是否正在执行/运行和/或上次执行。 【参考方案1】:

您可以选择自制还是使用 Oracle 的内置工具。

对于这种类型的 stat,我遇到的最可靠和最容易使用的方法是通过简单的 NOLOGGING INSERT 将本地代码登录到感兴趣的过程中,并插入到合适的表中。不要费心尝试复杂的求和,因为这会增加开销,只需一个简单的 INSERT,然后根据需要使用报告端进行汇总。您也可以添加时间戳和基本会话信息。

我看到的另一种我非常喜欢的新颖方法是,他们创建了一个与每个感兴趣的程序相对应的序列,并在每个程序开始时简单地选择 NEXTVAL。这不会为您提供基于历史/时间的统计信息;您会将其添加到报告方面,并且您需要了解 CACHE 对序列可能产生的影响。

就个人而言,我喜欢看到某种登录代码,因为它有助于解决支持/调试问题,提供对生产系统生命周期的真实洞察。此类信息可以推动改进。

话虽如此,Oracle 确实维护了一组丰富的统计数据,但提取和解释可能是深奥的。如果您可以访问 OEM/Grid COntrol(或者他们现在所称的基于 Web 的管理控制台),您可以查看时间框架之间的统计数据,并深入了解各个语句和过程。但这需要一些练习和专业知识,然后才能知道要寻找什么以及如何获得它。

您可以尝试滚动您自己的查询,专门针对感兴趣的过程。您将从 V$SQL 开始获取语句的 SQL_ID,然后将其链接到 DBA_HIST_SQLSTAT,后者维护统计数据的快照历史记录,包括总执行次数和自上次快照以来的执行次数。

如果您搜索 DBA_HIST_SQLSTAT 并执行,我相信您很快就会找到一个查询来帮助您入门。如果您不是 DBA,则需要被授予访问这些视图的权限。

【讨论】:

在没有任何日志记录的情况下执行插入的唯一方法是在没有索引的表上使用直接路径插入,这将需要排他表锁。我不确定您是否想这样做,尤其是对于单行。【参考方案2】:

如果您只需要它的使用次数(从某个任意重置时间)和上次使用的日期,请创建几个私有包变量。

package body package_name as
    F1_Use_Count integer := 0;
    F1_Last_Used timestamp;
    ...
    function F1 ...
        F1_Use_Count := F1_Use_Count + 1;
        F1_Last_Used := SysTimestamp;
        ... the rest of the function
     end F1;

     -- You also want to add
     function Get_F1_Use_Count return integer is begin
         return F1_Use_Count;
     end;
     function Get_F1_Last_Used return timestamp is begin
         return F1_Last_Used;
     end
     proc Reset_F1_Stats is begin
         F1_Use_Count := 0;
         F1_Last_Used := null;
     end;

     -- Or all three above could be done with
     proc Get_Reset_F1_Stats( Use_count out integer, Use_Date out timestamp ) is begin
         Use_count := F1_Use_Count;
         Use_Date := F1_Last_Used;
         F1_Use_Count := 0;
         F1_Last_Used := null;
      end;
end package_name;

编辑: 要“防会话”操作,请将值写入表而不是包变量。

CREATE TABLE Access_Stats(
    Proc_Id         VARCHAR2( 32 ) NOT NULL, 
    Access_Count    INTEGER DEFAULT 0 NOT NULL,
    Access_Date     DATE DEFAULT SYSDATE NOT NULL, 
    CONSTRAINT PK_TEST PRIMARY KEY( Proc_Id )
);

包体内:

Proc Set_Stats( PName Access_Stats.Proc_Id%type ) is begin
    MERGE INTO Access_Stats a
    USING(
        SELECT 1 FROM dual ) tt
    ON( a.Proc_Id  = Upper( PName ))
    WHEN MATCHED THEN
        UPDATE
            SET access_count  = access_count + 1,
                access_date   = SYSDATE
    WHEN NOT MATCHED THEN
        INSERT( Proc_Id, access_count )
        VALUES( Upper( PName ), 1 );

    Commit;
END;

然后在您要跟踪的所有函数和过程中,只需确保它们从调用 Set_Stats 过程开始:

Proc WhatEver...
    Set_Stats( 'whatever' );
...

getter 也必须更改为从表中读取。我会将 Get_Reset_F1_Stats 过程更改为更通用的 Get_Reset_Stats 版本:

 proc Get_Reset_Stats(
             PName Access_Stats.Proc_Id%type,
             Use_count out integer,
             Use_Date out timestamp )
 is begin
     Select  Access_Count, Access_Date
         into Use_count, Use_Date
     From    Access_Stats
     where   Proc_Id = Upper( PName );
     update  Access_Stats
         set Access_Count = 0
     where   Proc_Id = Upper( PName );
 end;

Get_Reset_Stats 可以只删除正在跟踪的过程的行,但通过将计数重置为零,重置的日期将被保留。如果添加其他字段,例如执行 proc 的用户,最后执行(或重置)被跟踪的过程/功能的人也可以保留。

我的标准警告适用:上面显示的代码更多地是为了说明而设计的,并不是作为生产就绪代码呈现的。修改以符合您自己的特定标准。

【讨论】:

这仅适用于每个会话,即如果有 10 个用户/连接调用此包,则收集的信息不会提供全局图片。 嗯,这不是所问问题的一部分,而且只有 10 个用户,发生这种情况的可能性至少可以说是微不足道的。但是,请参阅我的更新以获得解决此问题的一种方法。【参考方案3】:

你无法百分百确定

您可以查看上次编译包/过程的时间。 你可以看到其他对象依赖它 您可以在打包代码中搜索引用它的动态 sql,因为这不会显示在依赖项中 除非您查看报告,否则您无法判断报告是否调用了该对象 除非您在脚本中搜索,否则您无法判断外部脚本是否调用它 你无法判断对象是否被外部程序调用

【讨论】:

谢谢!我能够找到所有引用或引用,甚至是上次编译时...但是当我被要求提供的信息是它是否正在执行时,这真的无济于事......所以唯一的方法是放下它,看看有没有人抱怨?

以上是关于PL/SQL - 如何检查是不是正在使用包/过程/函数?的主要内容,如果未能解决你的问题,请参考以下文章

检查表是不是重复的过程 - Oracle PL/SQL

PL/SQL:在创建表之前检查模式中是不是有足够的空间

如何在 PL/SQL 中使用包内的过程

如何在 Oracle 中调试 PL/SQL 集合的值?

如何根据 PL/SQL 变量值检查输入参数值是不是存在作为列表?

PL/SQL 包 - 在包中调用过程