我正在尝试跟踪针对特定数据库用户执行的SQL语句。我没有启用AUDITING,我正在使用Oracle 11g。
我有以下查询:
SELECT
S.MODULE,
SQL_TEXT ,
S.EXECUTIONS
FROM
SYS.V_$SQL S,
SYS.ALL_USERS U
WHERE
S.PARSING_USER_ID=U.USER_ID
AND UPPER(U.USERNAME) IN ('USERNAME')
AND (UPPER(s.MODULE)='APP.EXE')
ORDER BY S.LAST_LOAD_TIME
但是如果运行'APP.EXE'的多个用户连接到同一个db用户,我无法理解哪个OS用户执行了哪个查询。所以我尝试加入V $ SESSION视图来获取用户详细信息。
SELECT
S.MODULE,SQL_TEXT ,SN.OSUSER, SN.MACHINE, S.EXECUTIONS
FROM
SYS.V_$SQL S,
SYS.ALL_USERS U,
V$SESSION SN
WHERE
S.PARSING_USER_ID=U.USER_ID
AND UPPER(U.USERNAME) IN ('USERNAME')
AND (UPPER(S.MODULE)='APP.EXE')
AND S.SQL_ID=SN.SQL_ID
ORDER BY S.LAST_LOAD_TIME
但这似乎不起作用(在我的情况下,它没有返回任何行) 所以,我有以下问题
1)如何获得每个会话执行的查询?
2)V_ $ SQL的EXECUTIONS列似乎是来自所有会话的执行。我如何知道会话执行特定查询的次数?
3)有关查询的记录将存储在V_ $ SQL中多长时间? Oracle何时从视图中删除它?
提前感谢你们,
与Pradeep
答案 0 :(得分:6)
如果不进行更多配置(例如启用审核)或做出一些妥协,您可能无法获得您正在寻找的数据。您尝试解决的业务问题是什么?根据问题,我们可以帮助您确定配置数据库的最简单方法,以便能够记录您所追踪的信息。
Oracle不会尝试存储特定用户执行特定查询的次数(特别是特定操作系统用户的次数)。 SQL_ID
中的V$SESSION
仅表示会话当前正在执行的SQL_ID
。如果,正如我猜测的那样,这是一个客户端 - 服务器应用程序,很可能99%的时间都是NULL,因为绝大多数时候,会话没有执行任何SQL,它正在等待用户做某事。 PREV_SQL_ID
中的V$SESSION
是先前执行的SQL语句 - 至少通常不是NULL
。但它只有一个值,它不会有该会话执行的SQL语句的历史记录。
V$SQL
视图表示SQL共享池中的内容。当SQL语句超出共享池时,它将不再位于V$SQL
视图中。这种情况发生的速度取决于多种因素 - 某人执行语句的频率,解析新语句的频率(通常在很大程度上取决于您的应用程序是否正确使用绑定变量),共享池的大小等等通常情况下,这将在几分钟之间,直到数据库关闭。
如果您被许可使用AWR表并且您对近似值感兴趣而不是完全正确的答案,那么您可以通过查看某些AWR表来获取您所需的信息。例如,V$ACTIVE_SESSION_HISTORY
将捕获每个会话每秒正在执行的SQL语句。但是,由于这是一个客户端 - 服务器应用程序,这意味着绝大多数情况下,会话将处于非活动状态,因此不会捕获任何内容。但是,碰巧会为会话捕获的SQL语句会让您对不同SQL语句的相对频率有所了解。当然,更长时间运行的SQL语句也更有可能被捕获,因为它们更有可能在给定的瞬间处于活动状态。如果查询A和B都执行完全相同的时间量并且会话被捕获执行A 5次并且B在过去一小时内执行10次,则可以得出结论B的执行大约是A的两倍。如果您知道查询的平均执行时间,捕获查询的平均概率将是查询执行的秒数(在0.5秒内执行的查询有50%的机会被捕获,一个在0.25执行秒有25%的可能性被捕获)因此您可以估计特定会话执行特定查询的频率。这与确切的数字相差甚远,特别是在较短的时间范围内,以及实际执行时间变化较大的查询。
V$ACTIVE_SESSION_HISTORY
视图中的数据通常可以使用几个小时。然后将其抽样到DBA_HIST_ACTIVE_SESS_HISTORY
表中,该表将可用数据量减少一个数量级,使得任何估计值都不太准确。但是,无论您的AWR保留间隔是多少,都会保留这些数据(默认情况下,这是一周,但许多站点将其增加到30或60天)。
答案 1 :(得分:0)
根据oracle文档
SQL_ADDRESS -Used with SQL_HASH_VALUE to identify the SQL statement that is currently being executed
SQL_HASH_VALUE - Used with SQL_ADDRESS to identify the SQL statement that is currently being executed
请参阅以下链接以供参考
请修改下面的SQL
SELECT S.MODULE, SQL_TEXT, SN.OSUSER, SN.MACHINE, S.EXECUTIONS
FROM SYS.V_$SQL S, SYS.ALL_USERS U, V$SESSION SN
WHERE S.PARSING_USER_ID = U.USER_ID
AND UPPER(U.USERNAME) IN ('USERNAME')
AND (UPPER(S.MODULE) = 'APP.EXE')
AND SN.sql_hash_value = S.hash_value
AND SN.sql_address = S.address
ORDER BY S.LAST_LOAD_TIME
答案 2 :(得分:0)
试试这个
SELECT l.Sql_Id FROM v $ session s JOIN v $ session_longops l ON l.sid = s.Sid AND l.Serial#= s.Serial#AND l.Start_Time> = s.Logon_Time WHERE s.Audsid = Sys_Context(' USERENV',' SESSIONID')
我假设您只对日志运行sql' s感兴趣?