ORA-60
Cuando se produce un error ORA-60 (Abrazo mortal - Deadlock detected), siempre hay 2 o más sesiones implicadas.
Este error se produce cuando hay esperas por recursos interdependientes entre varias sesiones de forma que nunca se llegarán a resolver.
Por ejemplo:
Vamos a ver un sencillo ejemplo de como se puede provocar. Aunque en el ejemplo se utilicen sentencias INSERT, también se puede provocar con sentencias UPDATE, DELETE o SELECT...FOR UPDATE
Vamos a partir de 2 sesiones (Ay B) y 2 tablas vacias (T1 y T2). En los casos reales, puede habetr más tablas y más sesiones implicadas.
La secuencia temporal de acciones que se realizan es:
- La sesión A ejecuta: INSERT INTO T1 VALUES (1);
- Con esta sentencia, se crea un bloqueo exclusivo sobre la tabla T1, registro 1
- La sesión B ejecuta: INSERT INTO T2 VALUES (1);
- Con esta sentencia, se crea un bloqueo exclusivo sobre la tabla T2, registro 1
- La sesión B ejecuta: INSERT INTO T1 VALUES (1);
- Esta sentencia no termina debido a que la sesión A tiene un bloqueo sobre este registro.
- La sesión B se espera a que la sesión A termine la transacción (COMMIT/ROLLBACK.)
- La sesión A ejecuta: INSERT INTO T2 VALUES (1);
- Esta sentencia no termina debido a que la sesión B tiene un bloqueo sobre este registro.
- La sesión A se espera a que la sesión B termine la transacción (COMMIT/ROLLBACK.)
En este momento, la sesión A espera que la B termine la transacción y la sesión B espera que la sesión A termine la transacción. Como consecuencia, ninguna de las dos transacciones puede continuar.
¿Qué hace Oracle cuando detecta un Abrazo Mortal?
La BBDD Oracle monitoriza los registros que hay en estado de espera y, cuando llevan cierto tiempo, mira si se ha producido un estado de Abrazo Mortal.
Si la BBDD Oracle detecta un Abrazo Mortal entre dos o más sesiones:
- Provoca en una de ellas (al azar) un error ORA-60.
- En esta sesión, hace rollback de la sentencia que estaba ejecutando en este momento. (que estaba en estado de espera).
- Con este rollback, se deshace el Abrazo Mortal.
- Genera un fichero de traza .trc donde indica, entre otras cosas:
- Sentencia que estaba ejecutando la sesión que ha recibido el error ORA-60
- Sesiones implicadas.
- Registros que tenian bloqueados cada una de estas sesiones.
- En esta sesión, hace rollback de la sentencia que estaba ejecutando en este momento. (que estaba en estado de espera).
¿Qué debemos hacer si se produce un error ORA-60?
Salvo algún bug, los errores ORA-60 son producidos por una mala práctica de programación. Por tanto, lo que hay que hacer es estudiar el fichero de traza generado por la BBDD y modificar el código de la aplicación para evitar caer es esta circunstancia.
Si observamos el ejemplo que hemos puesto, vemos que la dos sesiones A y B modifican (bloquean) las tablas T1 y T2 en orden distinto:
- La sesión A modifica T1 y después T2
- La sesión B modifica T2 y después T1
Una buena práctica de programación es hacer que, si en una transacción se modifican (bloquean) varias tablas, se haga siempre en el mismo orden.
Veamos que hubiera pasado en el ejemplo anterior si el orden de modificación hubiera sido el mismo en ambas sesiones:
- La sesión A ejecuta: INSERT INTO T1 VALUES (1);
- Con esta sentencia, se crea un bloqueo exclusivo sobre la tabla T1, registro 1
- La sesión B ejecuta: INSERT INTO T1 VALUES (1);
- La sesión B se espera a que la sesión A termine la transacción (COMMIT/ROLLBACK.)
- La sesión A ejecuta: INSERT INTO T2 VALUES (1);
- Con esta sentencia, se crea un bloqueo exclusivo sobre la tabla T2, registro 1
- En algún momento, la sesión A hace COMMIT/ROLLBACK;
- La sesión A libera el bloqueo que tenia sobre la tabla T1, registro 1
- La sesión B termina su insert (o bien se provoca un error de registro repetido)
- La sesión B puede realizar la sentencia INSERT INTO T2 VALUES (1);
Obsérvese que, quizás se provoque un error de Registro Repetido (o similar), pero no hay Abrazo Mortal.
