1. 程式人生 > >怎麼檢視使用者的SQL執行歷史

怎麼檢視使用者的SQL執行歷史

問題:如何知道一個session都執行過哪些SQL語句?(檢視當前比較容易,歷史的呢?怎麼復原sql的執行場景——事務關係、執行序列、單SQL還是儲存過程)

 

【方法一】查詢v$sqltext、v$sqlarea、v$sqlstats檢視

select * from v$sqlarea t where t.PARSING_SCHEMA_NAME in ('schema') order by t.LAST_ACTIVE_TIME desc;

#對v$sqltext、v$sqlarea檢視的是shared pool中的SQL,其時間索引是其解析歷史,因為共享的問題這個查詢可能並不能完整地反映出執行的歷史。

#v$sqlstats反應的是例項啟動起來的sql執行統計,sql語句本身比v$sqltext/area完整,因為後者有可能失效換出快取。

 

【方法二】

聯合v$active_session_history和v$sqlarea

#v$active_session_history 這個表只是個取樣資料,按秒進行,只有在那一秒取樣點處於on cpu或非idle等待的session統計在內。所以可能會不全,有些執行很短的SQL會忽略。這個檢視無法還原完整的session歷史。

#v$sqlarea中有執行過的SQL語句,但並無到session的關聯資訊,v$session中只關聯了當前的sql,所以也不行。

 

從v$sqlstat可以檢視到資料庫啟動起來的所有SQL資訊,但是沒有時間順序關係、沒有執行使用者資訊,只有執行次數與資源統計。

從dba_hist_sqlstat可以看到AWR snapshot之間的SQL統計資訊,與v$sqlstats比不受例項重啟的影響,因為例項重啟之後v$sqlstats中的資訊就清除了。

 

 

 

【方法三:session trace】

SQL> execute dbms_session.session_trace_enable(true,true);

PL/SQL procedure successfully completed.

 

SQL> select count(*) from dba_hist_sqltext;

 

  COUNT(*)

----------

       478

 

SQL> select * from V$sesstat where rownum=1;

 

       SID STATISTIC#      VALUE

---------- ---------- ----------

       134          0          1

 

SQL> execute dbms_session.session_trace_disable();

PL/SQL procedure successfully completed.

 

$ cd $ORACLE_HOME/admin/test/udump

$ ls -lrt

$ tkprof test_ora_2195620.trc report.txt sys=no explain=no  aggregate=yes

$ more report.txt     --這個檔案包括了啟停trace之間所有SQL語句的執行資訊,執行計劃、統計

 

【方法四:logminer】

只包含DML與DDL語句,不能查詢select語句。另外需要開啟supplemental logging,預設是沒有開啟的。

conn / as sysdba

--安裝LOGMINER

SQL> @$ORACLE_HOME/rdbms/admin/dbmslmd.sql;

SQL> @$ORACLE_HOME/rdbms/admin/dbmslm.sql;

SQL> @$ORACLE_HOME/rdbms/admin/dbmslms.sql;

SQL> @$ORACLE_HOME/rdbms/admin/prvtlm.plb;

 

--開啟附加日誌

alter database add supplemental log data;

 

--模擬DML操作

conn p_chenming/...

SQL> select * from test2;

SQL> insert into test2 values(7,77);

SQL> commit;

 

conn / as sysdba

--切歸檔

SQL> alter system switch logfile;

SQL> select name,dest_id,thread#,sequence# from v$archived_log; --最後一個即為新的歸檔

 

--新建LOG MINER

SQL> execute dbms_logmnr.add_logfile(logfilename=>'/oracle/archive_10g/test/test_1_138_786808434.arc',options=>dbms_logmnr.new); 

--開始miner

SQL> execute dbms_logmnr.start_logmnr(options=>dbms_logmnr.dict_from_online_catalog);

--檢視結果

SQL> col username format a8;

SQL> col sql_redo format a50 

SQL> select username,scn,timestamp,sql_redo from v$logmnr_contents where table_name='TEST2'; 

SQL> select username,scn,timestamp,sql_redo from v$logmnr_contents where username='P_CHENMING'; 

--關閉MINER

SQL> execute dbms_logmnr.end_logmnr;

--關閉輔助日誌

SQL> alter database drop supplemental log data;

 

【總結】

檢視v$sqlarea只能檢視粗略的歷史,因為很多SQL是共享的。

檢視ASH也不全,因為這是取樣資料,測試的時候基本沒有把SQL查詢出來。

檢視V$SQLSTATS能看到所有執行過的sql,以及其執行統計,但是沒有時序、沒有使用者資訊。

檢視TRACE應該是最完整的,但需要在執行SQL前開啟。

檢視logminer不能檢視select語句,而且預設的系統沒有開啟supplementing log,所以能檢視的內容有限。

或許還有審計的方法可用,我沒測試。每種方法都有各自的缺陷,看來很難有一種完備的檢視SQL執行歷史的方法。