lunes, 25 de agosto de 2014

Abrazo Mortal - SQL Server

En muchos de los talleres de bases de datos que dicto, muchos estudiantes me preguntan como resolver el problema del "abrazo mortal". En esta oportunidad, hablaré sobre la técnica para resolver este conflicto en SQL Server.

Anotaciones: SQL Server emite un error cuando detecta que hay un abrazo mortal (o deadlock, si lo prefieren) cuando un registro está siendo modificado por más de una conexión. Un ejemplo de esto lo ilustra la siguiente situación: La estación A quiere modificar los registros 1 y 2 y la estación B quiere modificar los registros 2 y 1. Ambas estaciones requieren que esos registros se modifiquen en ese orden.

Si el programa que intenta hacer ambas actualizaciones es capaz de detectar dicho error, entonces podrá resolver sin problemas la situación. Para esto, utilizaremos el mensaje de error 1205, que Microsoft describe como "Transaction (Process ID %d) was deadlocked on {%Z} resources with another process and has been chosen as the deadlock victim. Rerun the transaction."

Adicionalmente utilizaremos la función XACT_STATE() que devuelve cero cuando no hay transacciones activas en la conexión y menos unouno en caso contrario.

Para ilustrar dicho ejemplo, utilizaremos varios guiones, cada uno de los cuales realiza una función determinada.


Guión CREACIÓN. Creación de tablas y registros. Este guión no necesita mayor explicación. Crea una tabla con dos registros: Registro 1 y Registro 2.


create table abrazo ( a int not null primary key, valor int);
go

insert into abrazo values (1,1);
insert into abrazo values (2,2);


Seguidamente se entregan dos guiones que simularán las estaciones que desean modificar los registros según se explicó al inicio de este publicación


GUIÓN ESTACIÓN A. El funcionamiento de este guión establece un número de intentos hasta que la operación se ejecute. Si agotado el número de intentos la operación no se da, el programa termina. La línea señalada en azul es para que el programa haga una pausa y el usuario pueda probar ambos guiones simultáneamente en dos consolas de SQL Server. En sistemas en producción esto no debe hacerse.

Observe que este guión trata de modificar el registro 1 y luego el registro 2.




estacion_a


GUIÓN ESTACIÓN B. El funcionamiento de este guión es análogo al anterior sólo que éste intenta modificar el registro 2 y luego el registro 1. Recuerde que en el guión anterior, los registros se modifican en orden inverso: cuando el guión B intente modificar el registro 1, éste estará bloqueado por el guión A.



estacion_a


Resumen. Observe que ambos guiones solucionan entre ellos el problema del abrazo mortal. En general, los sistemas deben validar esta condición para garantizar que la operación se dé sin conflictos. En próximas entregas, se mostrará la solución del abrazo mortal para otros gestores de bases de datos.