2009-08-19 13 views
25

Estoy buscando una forma de averiguar si hay sentencias INSERT, UPDATE o DELETE sin compromiso en la sesión actual. Una forma sería verificar v $ lock con el sid actual, pero eso requiere acceso de lectura a v $ lock, que es un problema si el DBA no desea otorgarlo. ¿Alguna otra forma (aparte de hacer un seguimiento de todos los comandos de base de datos emitidos por la aplicación)?Oracle: ¿Cómo saber si hay una transacción pendiente?

+0

Supongo que no tengo acceso a ninguna vista en V $. – Gren

+0

posible duplicado de [¿Cómo puedo saber si he trabajado sin compromiso en una transacción de Oracle?] (Http://stackoverflow.com/questions/506456/how-can-i-tell-if-i-have-uncommitted-work -en-un-oráculo-transacción) –

Respuesta

34

se puede comprobar si la sesión tiene una fila en V$TRANSACTION (obviamente eso requiere privilegio de leer en esta vista):

SQL> SELECT COUNT(*) 
    2 FROM v$transaction t, v$session s, v$mystat m 
    3 WHERE t.ses_addr = s.saddr 
    4  AND s.sid = m.sid 
    5  AND ROWNUM = 1; 

    COUNT(*) 
---------- 
     0 

SQL> insert into a values (1); 

1 row inserted 

SQL> SELECT COUNT(*) 
    2 FROM v$transaction t, v$session s, v$mystat m 
    3 WHERE t.ses_addr = s.saddr 
    4  AND s.sid = m.sid 
    5  AND ROWNUM = 1; 

    COUNT(*) 
---------- 
     1 

SQL> commit; 

Commit complete 

SQL> SELECT COUNT(*) 
    2 FROM v$transaction t, v$session s, v$mystat m 
    3 WHERE t.ses_addr = s.saddr 
    4  AND s.sid = m.sid 
    5  AND ROWNUM = 1; 

    COUNT(*) 
---------- 
     0 
+0

Hay casos donde este método no funciona, devolviendo falsos positivos: por ejemplo, si selecciona datos de una base de datos remota utilizando un enlace de base de datos (seleccione * from remotetable @ databaselink) oráculo inicie una transacción incluso si no alteró ningún dato. Este método no garantiza que tenga datos no confirmados. ... ¿conoce alguna forma de mejorar esta consulta para filtrar transacciones de este tipo? Realmente me desconcierta –

+0

@CarloSirna Sí, hay casos en los que Oracle iniciará una transacción incluso si no modifica los datos. Conectarse a una base de datos remota es un ejemplo (vea por ejemplo [este hilo en Asktom] (https://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:8908307196113)) Un simple 'SELECT ...FOR UPDATE' también iniciará una transacción sin modificar los datos. El método descrito en mi respuesta indica si tiene una transacción pendiente, no si tiene datos no confirmados. Los dos no son equivalentes (la modificación de los datos es suficiente, pero no necesaria para iniciar una transacción). –

21

Esta es la consulta que normalmente uso,

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; 
+1

funciona muy bien, también necesitaba matar la transacción inactiva después con ALTER SYSTEM KILL SESSION 'sid, serial #'; – Diizzy

0

Matthew Watson puede ser modificado para ser utilizado en el 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; 
1

La solución más fácil y más fiable es tratar de iniciar una transacción y verlo si tiene éxito Si algún código ya inició una transacción pero aún no ha emitido ningún archivo DML, entonces la vista V $ TRANSACTION no mostrará nada.

En este ejemplo a continuación, manejo la excepción para generar un error de aplicación definido por el usuario. Para diferir a un manejador de excepciones existente, simplemente realice una TRANSACCIÓN CONJUNTA y luego COMIENCE de inmediato para deshacerla.

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