我遇到了错误的代码重复问题,我们无法分辨使用哪个版本的软件包/过程。即我有不同的程序包与相同名称的程序,我需要确定哪些程序包实际上没有被调用。
我正在尝试消除不再被调用的同名程序/包。我希望将跟踪运行几周,将数据组合在一起并查询元数据,并找到进一步调查和停用的候选者。
我正在寻找与sp_trace_setevent 42等效的SQL Server的sp_trace_create来跟踪SP:Starting事件 - 这将允许我查看所有正在调用的存储过程,然后将其与存储过程的整个库存进行比较以查看哪些应该首先调查是否过时。我已经使用DBMS_MONITOR.DATABASE_TRACE_ENABLE来生成跟踪文件,但是我没有找到任何解释如何使用TKPROF解析这些文件除了性能之外的任何东西 - 我甚至不关心语句本身,只是使用哪些例程。
答案 0 :(得分:3)
不要认为ILO会提供帮助(它不仅仅是设置模块和操作并将时间记录在某处吗?)因为Cade Roux必须修改数据库中的每个包和函数。
一种选择是在数据库中启用跟踪,
ALTER SYSTEM SET sql_trace = true SCOPE=MEMORY;
并使用脚本命令获取所有已执行包名称的唯一列表,但警告 - 这将产生大量输出并快速填满磁盘空间 - 您可能想创建一个程序文件每天运行,然后删除trc文件,然后将所有结果组合在一起,以确定使用哪些文件。
此外,您需要确保跟踪文件大小没有限制,这可能会阻止它记录所有内容并确保您有足够的磁盘空间,并且由于您对运行时不感兴趣,您还可以关闭timed_statistics以减少记录的数量。
alter system set max_dump_file_size=unlimited;
alter system set timed_statistics=false;
如果我查看从Oracle跟踪创建的原始跟踪文件,每个特定于应用程序的包调用过程调用都会显示为
=====================
PARSING IN CURSOR #2 len=69 dep=0 uid=102 oct=47 lid=102 tim=1316845390611021 hv=273704950
ad='b0d4c728' sqlid='01qnrr4850tzq'
BEGIN REIM_MATCH_SQL.INIT_SUMMARY_MATCH(:1, :2, :3, :4, :5, :6); END;
END OF STMT
PARSE #2:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=4,plh=0,tim=1316845390611021
所以你可以在目录中grep这样的包调用列表(如果tkprof输出不同,你可能需要稍微调整输出,具体取决于你使用的操作系统)
find . -name "*.trc" -exec grep "BEGIN " {} \; | cut -d" " -f4 | cut -d"(" -f1 | sort -u > ~/called_procedures.txt
这不适用于函数,因为它们可以在SQL语句中调用,但我认为对于过程,它应该没问题。这将在您的主目录中生成一个文件,其中包含自您打开跟踪以来已运行的唯一过程调用列表。
我在包含总共19GB磁盘空间的9818个跟踪文件的目录上进行了此操作,并且在运行具有2个内核和12GB内存的Oracle企业Linux 5的测试盒上花费了10分钟 - 这些跟踪文件仅来自重复的测试运行一个程序,所以你可以想象如果你为生产机器中的所有东西生成这些程序会有多快。
然后,您可以从sqlplus获取数据库中所有pacakges /过程的列表,了解您感兴趣的特定模式
set heading off
set trimspool on
set pagesize 0
set feedback off
spool all_procedures.txt
SELECT DISTINCT p.object_name||'.'||p.procedure_name
FROM all_procedures p
JOIN all_objects o ON (o.owner = p.owner AND o.object_name = p.object_name AND o.object_type =
where p.owner='&owner'
order by 1
spool off
最后做两个差异以获得候选人名单
diff all_procedures.txt called_procedures.txt
完成后不要忘记关闭跟踪
ALTER SYSTEM SET sql_trace = false SCOPE=MEMORY;
此外,您需要注意可能仅在月末或年末等特定时段运行的程序 - 它们可能看起来没有被使用但您无法确定除非每个业务流程在您完成期间完成正在监视。
希望有所帮助。
答案 1 :(得分:1)
正在运行的Oracle数据库会跟踪所有数据库对象的执行计数。可以通过v $ db_object_cache视图访问它。
select * from v$db_object_cache
where type in ('PROCEDURE');
你不需要的那些根本不会在列表中显示(从未加载)或将被列为0次执行。
答案 2 :(得分:0)
已从Oracle 10g中删除Oracle Trace功能。而应使用SQL Trace和TKPROF功能。
在应用程序服务器将语句传递给不同会话的多层环境中,从头到尾跟踪单个进程变得很困难。为了解决这个问题,Oracle引入了端到端应用程序跟踪,它允许通过客户端标识符而不是典型的会话ID来识别客户端进程。每条跟踪信息都链接到以下信息。
<强>参考:强>
http://www.oracle-base.com/articles/10g/PerformanceTuningEnhancements10g.php#tracing_enhancements
答案 3 :(得分:0)
您可以通过从架构LOGON和LOGOFF触发器调用DBMS_PROFILER来自动执行此操作。
--Run this script to install the profiler objects for the user
@...\RDBMS\ADMIN\proftab.sql
--Create some objects for testing
create or replace function test1 return varchar2 is
begin return 'test1'; end;
/
create or replace function test2 return varchar2 is
begin return test1(); end;
/
create or replace package test3 is
function test4 return varchar2;
function test5 return varchar2;
end;
/
create or replace package body test3 is
function test4 return varchar2 is begin return test2(); end;
function test5 return varchar2 is begin return 'test5'; end;
end;
/
--Create the LOGON trigger to start profiling
create or replace trigger profiler_logon after logon on test_schema.schema
begin
dbms_profiler.start_profiler(run_comment => sysdate);
end;
/
--Create the LOGOFF trigger to write the profiling data
create or replace trigger profiler_logoff before logoff on test_schema.schema
begin
dbms_profiler.stop_profiler();
dbms_profiler.flush_data();
end;
/
--Logon, run this:
select test3.test4() from dual;
select test3.test5() from dual;
--Logoff, logon, run this:
select test1() from dual;
--Logoff, logon to see results
--The data is stored in these tables.
select * from plsql_profiler_runs;
select * from plsql_profiler_units;
select * from plsql_profiler_data;
--Use a query like this to find the most common objects.
--But total_occur is both too low and too high:
-- It records at the object level, test4 and test5 are combined.
-- It seems to double many counts - maybe an extra call for initializing?
select unit_type, unit_owner, unit_name, sum(total_occur) total_occur
from plsql_profiler_units
join
(
--Get max number of times any line number was called.
select runid, unit_number, max(total_occur) total_occur
from plsql_profiler_data
where total_occur > 0
group by runid, unit_number
) profiler_data
on plsql_profiler_units.unit_number = profiler_data.unit_number
and plsql_profiler_units.runid = profiler_data.runid
where plsql_profiler_units.unit_type <> 'ANONYMOUS BLOCK'
group by unit_type, unit_owner, unit_name
order by total_occur desc, unit_type, unit_owner, unit_name;
UNIT_TYPE UNIT_OWNER UNIT_NAME TOTAL_OCCUR
--------- ---------- --------- -----------
FUNCTION TEST_SCHEMA TEST1 4
FUNCTION TEST_SCHEMA TEST2 2
PACKAGE BODY TEST_SCHEMA TEST3 2
但这里有很多问题:
性能 - profling会增加很多开销吗?我以前从未使用它,我不认为它是用于长期生产使用。您可能需要定期删除或截断数据。或者修改proftab.sql中的一些表;例如删除一些索引和外键。 (虽然我没试过,但可能会让事情变得更糟!)
无声失败 - 如果无法分析某些内容,它就不会显示出来。您需要非常小心,它适用于所有模式和对象。来自参考: “探查器仅收集用户具有CREATE权限的单元的数据;您不能使用该程序包来分析已授予EXECUTE ONLY访问权限的单元。通常,如果用户可以调试单元,则为同一用户但是,可以对一个单元进行分析,无论它是否已被编译为DEBUG。Oracle建议正在分析的模块应该编译为DEBUG,因为这提供了有关该单元在数据库中的附加信息。“
没有简单的方法可以找到包中使用的功能或程序。要获得此信息,您需要将dba_source.line中的行号与plsql_profiler_data.line#进行比较。不幸的是,这些查询可能非常困难,因为您需要解析PL / SQL。根据代码的简洁程度和简单程度,可能更容易手动完成代码并创建一个包含相关函数和过程开始和结束行号的表。
会话问题 - 注销触发器有时会失败吗?如果连接丢失,或者存在严重的数据库错误,我猜不会有 注销触发器已触发。在这种情况下,探查器信息不会写入表格。
您需要为所有用户设置此项,并合并其数据。或者你可以用同义词替换表到公共表?
你必须过滤掉很多垃圾,比如ANONYMOUS BLOCKS和其他奇怪的条目。