ORACLE中能否找到未提交事务的SQL语句

摘要:
在Oracle数据库中,我们可以找到SQL语句或未提交事务的其他相关信息吗?首先,我们在会话1中构造一个未提交的事务,如下所示:SQL˃createtabletest2as3select*from dba_objects;表已创建。SQL˃selectuserenvfromdual;USERENV-------------63SQL˃从测试中删除对象id=12;已删除1行。SQL˃然后在会话2中,我们使用以下SQL查询未提交的SQL语句。在不进行硬解析的情况下,可以方便地再次执行此SQL语句。但是,SharedPool的大小也受到限制。不可能无限制地缓存所有SQL执行计划。它使用LRU算法来管理库缓存。因此,您要查找的SQL语句可能已不在SharedPool中,并且已从SharedPool删除。

 

在Oracle数据库中,我们能否找到未提交事务(uncommit transactin)的SQL语句或其他相关信息呢?  关于这个问题,我们先来看看实验测试吧。实践出真知。

 

首先,我们在会话1(SID=63)中构造一个未提交的事务,如下所:

 

SQL> create table test
  2  as
  3  select * from dba_objects;
 
Table created.
SQL> select userenv('sid') from dual;
 
USERENV('SID')
--------------
           63
 
SQL> delete from test where object_id=12;
 
1 row deleted.
 
SQL> 

 

然后我们在会话2(SID=70)中,我们使用下面SQL查询未提交的SQL语句。如下所示:

 

SQL> select userenv('sid') from dual;
 
USERENV('SID')
--------------
            70
 
SQL> 
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');
SQL_TEXT                      : delete from test where object_id=12
-----------------
SQL_TEXT                      : select
grantee#,privilege#,nvl(col#,0),max(mod(nvl(option$,0),2))from objauth$ where
obj#=:1 group by grantee#,privilege#,nvl(col#,0) order by grantee#
-----------------
SQL_TEXT                      : SELECT /* OPT_DYN_SAMP */ /*+ ALL_ROWS
IGNORE_WHERE_CLAUSE NO_PARALLEL(SAMPLESUB)
opt_param('parallel_execution_enabled', 'false') NO_PARALLEL_INDEX(SAMPLESUB)
NO_SQL_TUNE */ NVL(SUM(C1),0), NVL(SUM(C2),0) FROM (SELECT /*+
IGNORE_WHERE_CLAUSE NO_PARALLEL("TEST") FULL("TEST") NO_PARALLEL_INDEX("TEST")
*/ 1 AS C1, CASE WHEN "TEST"."OBJECT_ID"=12 THEN 1 ELSE 0 END AS C2 FROM "TEST"
SAMPLE BLOCK (6.134372 , 1) SEED (1) "TEST") SAMPLESUB
-----------------
SQL_TEXT                      : select col#, grantee#,
privilege#,max(mod(nvl(option$,0),2)) from objauth$ where obj#=:1 and col# is
not null group by privilege#, col#, grantee# order by col#, grantee#
-----------------
SQL_TEXT                      : select
type#,blocks,extents,minexts,maxexts,extsize,extpct,user#,iniexts,NVL(lists,6553
5),NVL(groups,65535),cachehint,hwmincr,
NVL(spare1,0),NVL(scanhint,0),NVL(bitmapranges,0) from seg$ where ts#=:1 and
file#=:2 and block#=:3
-----------------
PL/SQL procedure successfully completed.

 

clip_image001

 

如上所示,这个SQL我们会查出很多不相关的SQL语句,接下来我们可以用下面的SQL查询(改用SQL Developer展示,因为SQL*Plus,不方便展示),如下所示,这个SQL倒不会查出不相关的SQL。但是这个SQL能胜任任何场景吗? 答案是否定的

 

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
WHERE  S.SADDR = T.SES_ADDR;

 

clip_image002

 

我们知道,在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语句,是一个不相关的SQL或者其值为Null。

 

clip_image003

 

接下来我们回滚SQL语句,然后继续新的实验测试,如下所示,在会话1(SID=63)里面执行了两个DML操作语句,都未提交事务。

 

SQL> delete from test where object_id=12;
 
1 row deleted.
 
SQL> update test set object_name='kkk' where object_id=14;
 
1 row updated.
 
SQL> 

 

 

接下来,我们使用SQL语句去查找未提交的SQL,发现只能捕获最开始执行的DELETE语句,不能捕获到后面执行的UPDATE语句。这个实验也从侧面印证了,我们不一定能准确的找出未提交事务的SQL语句。

 

 

clip_image004

 

 

所以结合上面实验,我们基本上可以给出结论,我们不一定能准确找出未提交事务的SQL语句,这个要视情况或场景而定。存在这不确定性。

 

 

 

参考资料:

 

https://asktom.oracle.com/pls/apex/f?p=100:11:0::::P11_QUESTION_ID:9523503800346688981

免责声明:文章转载自《ORACLE中能否找到未提交事务的SQL语句》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇NumPy-快速处理数据--ndarray对象--多维数组的存取、结构体数组存取、内存对齐、Numpy内存结构unity shader 变种(多重编译 multi_compile)下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

sysbench安装及使用

一、安装 1、下载地址: https://github.com/akopytov/sysbench/tree/0.5 2、上传到服务器 刚部署的服务器,可能没有编译环境(可安装编译环境:安装编译环境:yum groupinstall -y "development tools") Rz命令(如果服务器没有rz命令,可以安装:yum install lrz...

【网络】再谈select, iocp, epoll,kqueue及各种I/O复用机制 &amp;amp;&amp;amp; Reactor与Proactor的概念

首先,介绍几种常见的I/O模型及其区别,如下: blocking I/O nonblocking I/O I/O multiplexing (select and poll) signal driven I/O (SIGIO) asynchronous I/O (the POSIX aio_functions) blocking I/O这个不用多解释吧...

test命令

test命令:判断文件类型,判断文件权限,判段表达式,判断字符串,判断整数大小/相等,判断两文件新旧,inode号是否一样 判断文件类型 命令 功能 -b 文件 判断是块设备文件 -c 文件 判断是字符设备文件 -d 文件 判断是目录文件 -f 文件 判断是普通文件 -L 文件 判断是符号链接文件 -p 文件 判断是管道文...

Python的路径引用

1、以HOME目录为准,进行跳转 sys.path.append(os.path.dirname(__file__) + os.sep + '../') from config import swordfishconf from utils import log from utils.mysql_base import MySQLBase 将程序的HO...

Linux CentOS中使用SQL*Plus启动和关闭数据库

启动和关闭数据库的常用工具有三个 一、SQL*Plus 在SQL*Plus环境中,用户以SYSDBA身份连接到Oracle后,可以通过命令行方式启动或关闭数据库。 二、OEM(企业管理器) 利用OEM数据库控制台,可以完成数据库的启动与关闭操作。 三、RMAN 在Recovery Manager(RMAN)环境中可以通过命令行方式启动或关闭数据库。 一般...

layui 二级联动

layui 二级联动 HTML 部分 <form onsubmit="return false;"action="__SELF__"data-auto="true"method="post"class='form-horizontal layui-form' style='padding-top:20px'><input type="h...