我想找到一种方法来确定当前会话中是否存在未提交的INSERT、UPDATE或DELETE语句。一种方法是使用当前sid检查v$lock,但这需要读取v$lock,如果DBA不想授予访问权限,则会出现问题。除了跟踪应用程序发出的所有数据库命令之外,还有其他方法吗?
我想找到一种方法来确定当前会话中是否存在未提交的INSERT、UPDATE或DELETE语句。一种方法是使用当前sid检查v$lock,但这需要读取v$lock,如果DBA不想授予访问权限,则会出现问题。除了跟踪应用程序发出的所有数据库命令之外,还有其他方法吗?
您可以检查会话是否在V$TRANSACTION
中有一行(显然,这需要对此视图具有读取权限):
SQL> SELECT COUNT(*)
FROM v$transaction t, v$session s, v$mystat m
WHERE t.ses_addr = s.saddr
AND s.sid = m.sid
AND ROWNUM = 1;
COUNT(*)
----------
0
SQL> insert into a values (1);
1 row inserted
SQL> SELECT COUNT(*)
FROM v$transaction t, v$session s, v$mystat m
WHERE t.ses_addr = s.saddr
AND s.sid = m.sid
AND ROWNUM = 1;
COUNT(*)
----------
1
SQL> commit;
Commit complete
SQL> SELECT COUNT(*)
FROM v$transaction t, v$session s, v$mystat m
WHERE t.ses_addr = s.saddr
AND s.sid = m.sid
AND ROWNUM = 1;
COUNT(*)
----------
0
SELECT ... FOR UPDATE
也会启动一个事务而不修改数据。我回答中描述的方法告诉您是否有待处理的事务,而不是未提交的数据。这两者并不等价(修改数据足以但不必要启动事务)。 - Vincent Malgrat这是我通常使用的查询语句:
select s.sid
,s.serial#
,s.username
,s.machine
,s.status
,s.lockwait
,t.used_ublk
,t.used_urec
,t.start_time
from v$transaction t
inner join v$session s on t.addr = s.taddr;
SELECT * FROM V$TRANSACTION
WHERE STATUS='ACTIVE';
请参考: http://forums.oracle.com/forums/thread.jspa?threadID=691061
select dbms_transaction.step_id from dual
参考资料:
select dbms_transaction.step_id from dual;
相比,它相当复杂。step_id返回:如果没有事务,则为NULL;如果存在事务但为空,则为0;如果有任何待处理更改,则为非空、非零值。在我看来,这比你的版本简单得多,并告诉我们更多关于连接状态的信息。你是否发现step_id存在不可靠的问题? - quetzalcoatl最简单可靠的解决方案是尝试启动事务并查看是否成功。如果某些代码已经启动了事务但尚未发出任何DML,则V$TRANSACTION视图将不显示任何内容。
在下面的示例中,我处理异常以引发用户定义的应用程序错误。要推迟到现有的异常处理程序,只需执行 SET TRANSACTION 然后立即 COMMIT 以撤消它。
DECLARE
transaction_in_progress EXCEPTION;
PRAGMA EXCEPTION_INIT(transaction_in_progress, -1453);
BEGIN
SET TRANSACTION NAME 'CHECK_FOR_TRANSACTION_ALREADY_SET';
COMMIT; -- end transaction
EXCEPTION
WHEN transaction_in_progress THEN
RAISE_APPLICATION_ERROR(-20000,'Transaction is already in progress');
END;
/
Matthew Watson可以被修改以用于RAC
select t.inst_id
,s.sid
,s.serial#
,s.username
,s.machine
,s.status
,s.lockwait
,t.used_ublk
,t.used_urec
,t.start_time
from gv$transaction t
inner join gv$session s on t.addr = s.taddr;