1. 程式人生 > 其它 >ORACLE中能否找到未提交事務的SQL語句

ORACLE中能否找到未提交事務的SQL語句

首先,我們在會話1(SID=63)中構造一個未提交的事務,如下:

SQL> create table test as select * from dba_objects;
SQL> select userenv('sid') from dual;
SQL> delete from test where object_id=12;

然後我們在會話2(SID=70)中,我們使用下面SQL查詢未提交的SQL語句。如下所示:

SQL> select userenv('sid') from dual;
USERENV('SID')
--------------
            70
SQL> SET SERVEROUTPUT ON SIZE 99999; SQL> EXECUTE PRINT_TABLE('SELECT SQL_TEXT FROM V$SQL S,V$TRANSACTION T WHERE S.LAST_ACTIVE_TIME=T.START_DATE');
SELECT  S.SID
       ,S.SERIAL#
       ,S.USERNAME
       ,S.OSUSER 
       ,S.PROGRAM 
       ,S.EVENT
       ,TO_CHAR(S.LOGON_TIME,'YYYY-MM-DD HH24:MI:SS
') ,TO_CHAR(T.START_DATE,'YYYY-MM-DD HH24:MI:SS') ,S.LAST_CALL_ET ,S.BLOCKING_SESSION ,S.STATUS ,( SELECT Q.SQL_TEXT FROM V$SQL Q WHERE Q.LAST_ACTIVE_TIME=T.START_DATE AND ROWNUM<=1) AS SQL_TEXT
FROM V$SESSION S, V$TRANSACTION T WHERE S.SADDR = T.SES_ADDR;

我們知道,在ORACLE裡第一次執行一條SQL語句後,該SQL語句會被硬解析,而且執行計劃和解析樹會被快取到Shared Pool裡。方便以後再次執行這條SQL語句時不需要再做硬解析。但是Shared Pool的大小也是有限制的,不可能無限制的快取所有SQL的執行計劃,它使用LRU演算法管理庫快取記憶體區。所以有可能你要找的SQL語句已經不在Shared Pool裡面了,它從Shared Pool被移除出去了。如下所示,我們使用sys.dbms_shared_pool.purge人為構造SQL被移除出Shared Pool的情況。如下所示:

SQL> col sql_text for a80;
SQL> select sql_text
2 ,sql_id
3 ,version_count
4 ,executions
5 ,address
6 ,hash_value
7 from v$sqlarea where sql_text
8 like 'delete from test%';

SQL_TEXT SQL_ID VERSION_COUNT EXECUTIONS ADDRESS HASH_VALUE
------------------------------------ ------------- ------------- ---------- ---------------- ----------
delete from test where object_id=12 5xaqyzz8p863u 1 1 0000000097FAE648 3511949434

SQL> exec sys.dbms_shared_pool.purge('0000000097FAE648,3511949434','C');
PL/SQL procedure successfully completed.

此時我們查詢到的SQL語句,是一個不相關的SQL或者其值為Null。

所以結合上面實驗,我們基本上可以給出結論,我們不一定能準確找出未提交事務的SQL語句,這個要視情況或場景而定。存在這不確定性。