Oracle 甲骨文:如何找出是否有一个交易悬而未决?

Oracle 甲骨文:如何找出是否有一个交易悬而未决?,oracle,transactions,Oracle,Transactions,我正在寻找一种方法来确定当前会话中是否有未限制的INSERT、UPDATE或DELETE语句。一种方法是使用当前sid检查v$lock,但这需要对v$lock进行读取访问,如果DBA不想授予它,这将是一个问题。除了跟踪应用程序发出的所有数据库命令之外,还有其他方法吗 SELECT * FROM V$TRANSACTION WHERE STATUS='ACTIVE'; 见: 您可以检查您的会话是否在V$TRANSACTION中有一行显然需要此视图的读取权限: SQL> SELECT COU

我正在寻找一种方法来确定当前会话中是否有未限制的INSERT、UPDATE或DELETE语句。一种方法是使用当前sid检查v$lock,但这需要对v$lock进行读取访问,如果DBA不想授予它,这将是一个问题。除了跟踪应用程序发出的所有数据库命令之外,还有其他方法吗

SELECT * FROM V$TRANSACTION
WHERE STATUS='ACTIVE';
见:

您可以检查您的会话是否在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 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;

使用下面的查询查找挂起的事务

如果它返回一个值,则表示有一个挂起的事务

以下是查询:

从dual中选择dbms_transaction.step_id

参考资料:

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;

最简单和最可靠的解决方案是尝试并启动一个事务,看看它是否成功。如果一些代码已经启动了一个事务,但是还没有发布任何DML,那么V$transaction视图将不会显示任何内容

在下面的示例中,我处理异常以引发用户定义的应用程序错误。要遵从现有的异常处理程序,只需执行一个SET事务,然后立即提交以撤消它

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;
/

我假设您没有访问任何V$视图的权限。对于未提交的事务,我们还可以获取sql_文本的可能副本。:-不同的描述。。。未提交的工作与挂起的事务工作得非常好,我还需要在使用ALTER SYSTEM kill会话'sid,serial'后终止非活动事务;有些情况下,此方法不起作用,返回误报:例如,如果您只是使用数据库链接select*from从远程数据库中选择数据remotetable@databaselink即使您没有更改任何数据,oracle也会启动事务。此方法不能保证您有未提交的数据。。。您知道如何改进此查询以过滤掉此类事务吗?这真的让我很困惑。@CarloSirna是的,在有些情况下,即使您不更改数据,Oracle也会启动事务。连接到远程数据库就是一个例子,请参见示例。一个简单的选择。。。FOR UPDATE还将在不修改数据的情况下启动事务。我的回答中描述的方法告诉您是否有待处理的事务,而不是是否有未提交的数据。这两种方法并不等同。修改数据就足够了,但启动事务时不需要。请执行一个设置事务,然后运行您的查询。@PeterNosko:您建议的解决方案工作得很好,但与简单的select dbms_transaction.step_id from dual相比非常复杂;正如DBA所建议的那样。步骤id返回:如果没有事务,则返回NULL;如果事务存在但为空,则返回0;如果有任何挂起的更改,则返回非NULL、非零值。这比你的版本简单得多,告诉我们更多关于连接状态的信息。您是否发现step_id有任何问题导致其不可靠?