2009-10-15 17 views
7

¿Hay alguna manera de probar si una fila se ha bloqueado para la actualización en Oracle?¿Cómo verifica si una fila está bloqueada para la actualización?

A modo de ejemplo, supongamos que la siguiente consulta, realizada por un usuario:

select * from SOME_TABLE where THE_ID = 1000 for update; 

con otro usuario que quiero comprobar si la fila con THE_ID = 1000 está bloqueado. Si intento una actualización o algo, el segundo usuario se bloquea y sigue esperando (no quiero eso).

también he tratado de ejecutar la siguiente consulta con el segundo usuario:

select * from SOME_TABLE where THE_ID = 1000 for update NOWAIT; 

Ya que no puedo colocar dos enganches en la misma fila se producirá un error. Y lo hace. Obtengo un "ORA-00054: recurso ocupado y adquiero con el error especificado NOWAIT". ¿Puedo contar siempre con este error para verificar la presencia del bloqueo, o hay una manera más simple y más clara de determinar si una fila está bloqueada?

Gracias!

+1

que debiera obtener este error "ORA-00054: recurso ocupado y adquirir con NOWAIT especificado" - ¿está seguro de que su usuario puede ver la tabla? – SeriousCallersOnly

+0

@ SeriousCallersOnly: Gracias, de hecho tengo el "ORA-00054: recurso ocupado y adquiero con el error especificado NOWAIT". El ORA-00942 fue lanzado por otra capa de mi aplicación. Lo siento por eso. Editaré la pregunta. –

Respuesta

14

Se puede escribir un procedimiento con el FOR UPDATE NOWAIT y devolverá un mensaje de error cuando la fila está bloqueado:

SQL> CREATE OR REPLACE PROCEDURE do_something(p_id NUMBER) IS 
    2  row_locked EXCEPTION; 
    3  PRAGMA EXCEPTION_INIT(row_locked, -54); 
    4 BEGIN 
    5  FOR cc IN (SELECT * 
    6     FROM some_table 
    7     WHERE ID = p_id FOR UPDATE NOWAIT) LOOP 
    8  -- proceed with what you want to do; 
    9  NULL; 
10  END LOOP; 
11 EXCEPTION 
12  WHEN row_locked THEN 
13  raise_application_error(-20001, 'this row is locked...'); 
14 END do_something; 
15/

Procedure created 

Ahora vamos a construir un pequeño ejemplo con dos sesiones:

session_1> select id from some_table where id = 1 for update; 

     ID 
---------- 
     1 

session_2> exec do_something(1); 

begin do_something(1); end; 

ORA-20001: this row is locked... 
ORA-06512: at "VNZ.DO_SOMETHING", line 11 
ORA-06512: at line 2 

session_1> commit; 

Commit complete 

session_2> exec do_something(1); 

PL/SQL procedure successfully completed 
+0

Como ya respondí a SeriousCallersOnly, estoy teniendo el error ORA-00054. Gracias. ¿Pero puedo contar con él para verificar el bloqueo? –

+0

@dpb: puede confiar en este mecanismo. Agregué un pequeño ejemplo que muestra cómo funcionaría el procedimiento con dos sesiones bloqueando la misma fila. –

1

No es ni simple ni limpio, pero la información está disponible en las vistas V$LOCK y V$SESSION.

Sin embargo, si sientes la necesidad de utilizar algo como esto como parte del código de tu aplicación normal, debes pensarlo de nuevo. A las aplicaciones no les debería importar cómo se bloquea la base de datos. Si te encuentras en un callejón sin salida, necesitas reestructurar tus consultas para que no sucedan.

Cuestiones relacionadas