sql >> Base de Datos >  >> RDS >> Oracle

Interbloqueos en Oracle

Quiero hacer una secuencia de comandos donde las sesiones de Oracle que entran en un punto muerto se eliminen automáticamente

EDITAR Se explicó mejor, se corrigieron algunas oraciones y se agregó un caso de prueba para demostrar el escenario de punto muerto.

¿Por qué quieres reinventar la rueda? Oracle detecta un interbloqueo automáticamente, arroja ORA-00060: deadlock detected while waiting for resource , y revierte una de las transacciones involucradas en el interbloqueo que Oracle decidió como víctima. Las transacciones exitosas anteriores no se revierten. Incluso después del error de interbloqueo, si se emite una confirmación, se confirmará la transacción exitosa anterior. En este momento, la transacción de la otra sesión también tendrá éxito y podrías emitir una confirmación. No hay nada que deba hacer explícitamente aquí. Los interbloqueos se borran automáticamente; nunca es necesario borrar ellos.

Por lo general, Oracle tarda uno o dos segundos en detectar un interbloqueo y arroja el error.

Puede probar con un caso de prueba simple como se muestra aquí:Comprensión de Oracle Deadlock

Veamos un caso de prueba -

SQL> CREATE TABLE t_test(col_1 NUMBER, col_2 NUMBER);

Table created
SQL> INSERT INTO t_test VALUES(1,2);

1 row inserted
SQL> INSERT INTO t_test VALUES(3,4);

1 row inserted

SQL> COMMIT;

Commit complete

SQL> SELECT * FROM t_test;

     COL_1      COL_2
---------- ----------
         1          2
         3          4

Tenga en cuenta el tiempo de cada transacción, he establecido el tiempo de sincronización para una mejor comprensión.

SESIÓN:1

12:16:06 SQL> UPDATE t_test SET col_1 = 5 WHERE col_2=2;

1 row updated.

Elapsed: 00:00:00.00

SESIÓN:2

12:16:04 SQL> UPDATE t_test SET col_1 = 6 WHERE col_2=4;

1 row updated.

Elapsed: 00:00:00.00
12:16:31 SQL> UPDATE t_test SET col_1 = 7 WHERE col_2=2;

En este punto, SESIÓN 2 sigue esperando .

SESIÓN:1

12:16:15 SQL> UPDATE t_test SET col_1 = 8 WHERE col_2=4;

En este punto, SESIÓN 2 es víctima de punto muerto, SESIÓN 1 todavía está esperando

Veamos los detalles de la sesión de SESIÓN 2 -

12:22:15 SQL> select sid,status,program,sql_id, state, wait_class, blocking_session_status, event from v$session where schemaname='LALIT' and program='sqlplus.exe';

       SID STATUS   PROGRAM         SQL_ID        STATE               WAIT_CLASS      BLOCKING_SE EVENT
---------- -------- --------------- ------------- ------------------- --------------- ----------- ----------------------------------------------------------------
        14 ACTIVE   sqlplus.exe     60qmqpmbmyhxn WAITED SHORT TIME   Network         NOT IN WAIT SQL*Net message to client
       134 ACTIVE   sqlplus.exe     5x0zg4qwus29v WAITING             Application     VALID       enq: TX - row lock contention

Elapsed: 00:00:00.00
12:22:18 SQL>

Entonces, v$session detalles cuando se ven en SESIÓN 2 , es decir, SID 14, dice que el estado es ACTIVO .

Veamos los detalles de la sesión de otra sesión, llamémosla SESIÓN 3 en aras. Recuerda, SESIÓN 1 todavía está esperando.

SQL> set time on timing on
12:24:41 SQL> select sid,status,program,sql_id, state, wait_class, blocking_session_status, event from v$session where schemaname='LALIT' and program='sqlplus.exe'

       SID STATUS   PROGRAM         SQL_ID        STATE               WAIT_CLASS BLOCKING_SE EVENT
---------- -------- --------------- ------------- ------------------- ---------- ----------- ------------------------------
        13 ACTIVE   sqlplus.exe     60qmqpmbmyhxn WAITED SHORT TIME   Network    NOT IN WAIT SQL*Net message to client
        14 INACTIVE sqlplus.exe                   WAITING             Idle       NO HOLDER   SQL*Net message from client
       134 ACTIVE   sqlplus.exe     5x0zg4qwus29v WAITING             Applicatio VALID       enq: TX - row lock contention
                                                                      n


Elapsed: 00:00:00.01
12:24:44 SQL>

Entonces, para otras sesiones, SESIÓN 2 , es decir, SID 14, es INACTIVO . SESIÓN 1 todavía está ESPERANDO con evento enq: TX - row lock contention .

Comprometámonos SESIÓN 2 -

12:22:18 SQL> commit;

Commit complete.

Elapsed: 00:00:00.01
12:25:43 SQL>

En este punto, se libera el bloqueo para SESIÓN 1 , confirmemos también la sesión 1 -

12:16:15 SQL> UPDATE t_test SET col_1 = 8 WHERE col_2=4;

1 row updated.

Elapsed: 00:08:27.29
12:25:43 SQL> commit;

Commit complete.

Elapsed: 00:00:00.00
12:26:26 SQL>

Elapsed: 00:08:27.29 muestra SESIÓN 1 estaba esperando tanto tiempo hasta la SESIÓN 2 fue cometido.

Para resumir, aquí está la historia completa de la sesión 1 -

12:16:06 SQL> UPDATE t_test SET col_1 = 5 WHERE col_2=2;

1 row updated.

Elapsed: 00:00:00.00
12:16:15 SQL> UPDATE t_test SET col_1 = 8 WHERE col_2=4;

1 row updated.

Elapsed: 00:08:27.29
12:25:43 SQL> commit;

Commit complete.

Elapsed: 00:00:00.00
12:26:26 SQL>

Para resumir, aquí está la historia completa de la sesión 2 -

12:16:04 SQL> UPDATE t_test SET col_1 = 6 WHERE col_2=4;

1 row updated.

Elapsed: 00:00:00.00
12:16:31 SQL> UPDATE t_test SET col_1 = 7 WHERE col_2=2;
UPDATE t_test SET col_1 = 7 WHERE col_2=2
                                  *
ERROR at line 1:
ORA-00060: deadlock detected while waiting for resource


Elapsed: 00:00:24.47
12:22:15 SQL> select sid,status,program,sql_id, state, wait_class, blocking_session_status, event from v$session where schemaname='LALIT' and program='sqlplus.exe';

       SID STATUS   PROGRAM         SQL_ID        STATE               WAIT_CLASS      BLOCKING_SE EVENT
---------- -------- --------------- ------------- ------------------- --------------- ----------- ----------------------------------------------------------------
        14 ACTIVE   sqlplus.exe     60qmqpmbmyhxn WAITED SHORT TIME   Network         NOT IN WAIT SQL*Net message to client
       134 ACTIVE   sqlplus.exe     5x0zg4qwus29v WAITING             Application     VALID       enq: TX - row lock contention

Elapsed: 00:00:00.00
12:22:18 SQL> commit;

Commit complete.

Elapsed: 00:00:00.01
12:25:43 SQL>

Ahora, veamos qué transacción se revirtió y cuál se comprometió -

12:25:43 SQL> select * from t_test;

     COL_1      COL_2
---------- ----------
         5          2
         8          4

Elapsed: 00:00:00.00
12:30:36 SQL>

Conclusión

En mi opinión, la mejor manera de conocer los detalles de la sesión de un interbloqueo es registrar los detalles de la forma más detallada posible. De lo contrario, es una pesadilla para un DBA investigar sin registrar la información adecuada. De hecho, incluso un desarrollador encontraría que es una tarea hercúlea rectificar y corregir la falla de diseño real si los detalles del error de interbloqueo no se registran detalladamente. Y para concluir con una declaración de una sola línea, un punto muerto se debe a una falla de diseño, Oracle es solo la víctima y la aplicación es la culpable. Los interbloqueos dan miedo, pero señalan las fallas de diseño que deben corregirse tarde o temprano.