问题:如何知道一个session都执行过哪些SQL语句?(查看当前比较容易,历史的呢?怎么复原sql的执行场景——事务关系、执行序列、单SQL还是存储过程)






除了PL/SQL的ctrl+e的查看方法外还有如下方法:






【方法一】查询v$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; 
 
 
 

 
 

 
 

   ---------- 
 
 
 
   
     
     
  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 
 
 
 
aggregate=yes


 






【方法四: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 
 
 
 

 
 

   --开始miner 
 
 
 

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

   --查看结果 
 
 
 

   SQL> col username format a8; 
 
 
 

 
 

 
 

 
 

   --关闭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执行历史的方法。