能否通过Oracle系统表查看存储过程(含参数)的调用历史?
首先得明确:默认情况下Oracle不会自动记录存储过程的实际调用参数,但可以通过以下几种系统表/视图或配置来获取相关信息,具体取决于你的环境设置:
1. 利用V$SQL和V$SQL_BIND_CAPTURE关联查询
虽然你说在V$SQL没找到,但可能是过滤条件不对——包内存储过程的调用语句在V$SQL里通常是类似BEGIN 包名.存储过程名(:1,:2); END;这样的格式。你可以先通过V$SQL定位到对应的调用语句,再关联V$SQL_BIND_CAPTURE获取绑定的参数值:
SELECT s.sql_id, s.sql_text, bc.name AS bind_parameter, bc.value_string AS parameter_value, bc.last_captured FROM v$sql s JOIN v$sql_bind_capture bc ON s.sql_id = bc.sql_id WHERE s.sql_text LIKE '%BEGIN 你的包名.你的存储过程名%' OR s.sql_text LIKE '%CALL 你的包名.你的存储过程名%' ORDER BY bc.last_captured DESC;
注意:V$SQL_BIND_CAPTURE只记录被Oracle标记为"绑定变量"的参数,而且短生命周期的调用可能被共享池冲刷掉,数据不会永久保存。
2. 检查DBA_HIST_SQLBIND(AWR历史数据)
如果你的数据库开启了AWR(自动工作负载仓库),可以查询DBA_HIST_SQLBIND视图——它保存了V$SQL_BIND_CAPTURE的历史快照数据,适合查找较久之前的调用记录:
SELECT h.snap_id, h.sql_id, h.name AS bind_parameter, h.value_string AS parameter_value, s.begin_interval_time AS capture_time FROM dba_hist_sqlbind h JOIN dba_hist_snapshot s ON h.snap_id = s.snap_id WHERE h.sql_id IN ( SELECT sql_id FROM dba_hist_sqltext WHERE sql_text LIKE '%BEGIN 你的包名.你的存储过程名%' ) ORDER BY s.begin_interval_time DESC;
前提是AWR的保留周期足够长,且目标调用记录被快照捕获。
3. 启用审计功能(需DBA权限)
如果上述视图都没有数据,你可以考虑开启Oracle的审计功能来记录存储过程的调用及参数:
- 首先开启审计(需要重启数据库生效):
ALTER SYSTEM SET audit_trail=DB,EXTENDED SCOPE=SPFILE;
- 重启后创建审计规则:
AUDIT EXECUTE ON 你的包名 BY ACCESS;
之后调用记录会存储在DBA_AUDIT_TRAIL视图中,SQLBIND字段会包含绑定参数信息:
SELECT username, timestamp, obj_name AS package_procedure, sqlbind AS parameters FROM dba_audit_trail WHERE obj_name = '你的包名' AND action_name = 'EXECUTE' ORDER BY timestamp DESC;
注意:审计会增加系统开销,需要和DBA确认是否可以启用。
4. 实时查看正在运行的调用
如果存储过程正在被执行,可以通过实时会话视图查看当前的参数:
SELECT s.sid, s.serial#, s.username, cs.sql_text, bc.name AS bind_parameter, bc.value_string AS parameter_value FROM v$session s JOIN v$session_current_sql cs ON s.sid = cs.sid JOIN v$sql_bind_capture bc ON cs.sql_id = bc.sql_id WHERE cs.sql_text LIKE '%BEGIN 你的包名.你的存储过程名%';
这个只能查看正在运行的调用,无法获取历史记录。
总结一下:如果之前没有开启审计或相关追踪,可能无法获取到完整的历史参数记录;但可以尝试通过V$SQL_BIND_CAPTURE和AWR的历史视图去查找已捕获的记录。如果需要长期稳定记录,建议启用审计或者后续在存储过程中添加自定义日志逻辑(虽然同事没做,但这是长期解决方案)。
内容的提问来源于stack exchange,提问作者Andrey

