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

PL/SQL - How can I check if a Package / Procedure / Function is being used?

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

我只需要知道 Package/Procedure/Function 是否正在使用 and/or,上次使用的时间。有没有办法通过 PL/SQL 开发人员的查询或功能查看它?

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

你不能 100% 肯定地说

  • 你可以看到最后一次编译package/procedure。
  • 可以看到还有哪些对象依赖它
  • 您可以在打包代码中搜索引用它的动态 sql,因为它不会显示在依赖项中
  • 除非查看报告,否则无法判断报告是否调用了对象
  • 除非在脚本中搜索,否则无法判断外部脚本是否调用了它
  • 您无法判断该对象是否被外部程序调用

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

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;

编辑: 对于 "session-proof" 操作,将值写入 table 而不是包变量。

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' );
...

吸气剂也必须更改为从 table 读取。我会将 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的用户等其他字段,还可以维护上次执行(或重置)被跟踪的procedure/function的人

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

您可以选择朴素和使用 Oracle 的内置工具。

对于这种类型的统计,我遇到的最可靠和最容易访问的方法是通过简单的 NOLOGGING INSERT 到 suitable table.不要费心尝试复杂的求和,因为这会增加开销,只需一个简单的 INSERT,然后使用报告端根据需要进行汇总。您也可以添加时间戳和基本会话信息。

我看到的另一种我非常喜欢的新颖方法是,他们创建了一个与每个感兴趣的程序相对应的序列,并在每个程序开始时简单地选择 NEXTVAL。这不会为您提供基于 historic/time 的统计数据;您会将其添加到报告端,您将需要了解缓存对序列的影响。

就个人而言,我喜欢看到某种登录代码,因为它有助于解决 support/debug 问题,提供对生产系统日常工作的真正洞察力。这些信息可以推动改进。

话虽如此,Oracle 确实维护着一组丰富的统计数据,但提取和解释可能很深奥。如果您可以访问 OEM/Grid COntrol(或如今他们称之为基于 Web 的管理控制台的任何东西),您可以查看时间范围之间的统计数据,并深入到各个报表和过程。但这需要一些练习和知识,然后您才能知道要寻找什么以及如何获得它。

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

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