Sei sulla pagina 1di 6

www.trucosaxapta.

com

Transacciones y bloqueos en SQL-Server


(Informacin para el uso desde Axapta)

Introduccin
En este documento vamos a intentar explicar cuatro conceptos bsicos acerca de las transacciones y los bloqueos en SQL-Server y lo ms importante: como los evita/gestiona Axapta cuando puede. Y cuando no puede algn truquillo para ayudarle.

Transacciones
Si a mitad de ejecutar un proceso se produce un error, no podemos asegurar la integridad de los datos actualizados por nuestra aplicacin. Es decir, si tenamos que actualizar 500 registros de la Base de datos y se ha producido un error cuando habamos procesado tan solo 200 los otros 300 quedan sin actualizar. En muchos ocasiones esto no es para nada deseable (imaginemos una facturacin, se nos produce un error a mitad de procesar los pedidos incluidos en una factura y quedan pedidos marcados como facturados y otros que no y la factura podra no haberse completado). Para evitar este problema existen las transacciones. Una transaccin es un sistema que utilizan las BBDD para saber cuando un proceso termina satisfactoriamente. Podramos decir que es un todo o nada. El tema consiste en que nuestro proceso realiza las actualizaciones que necesita en la base de datos y cuando ha terminado todo el proceso le indica al SQL que todo lo que ha realizado puede darlo por bueno. Por el contrario si hay algn problema, la base de datos dispone de un mecanismo que le permite anular todos los cambios realizados en los datos durante ese proceso. En Axapta, para saber que actualizaciones de la BBDD pertenecen al mismo lote deberemos indicar donde empieza y termina cada transaccin: ttsbegin; // principio de la transaccin // instrucciones de actualizacin ttscommit; // final de la transaccin

www.trucosaxapta.com Si no se produce ningn error, se ejecutar la instruccin de fin de transaccin y la BBDD guardar las actualizaciones que se han realizado dentro de la transaccin. En cambio, si existiese un error se producira un RollBack que consiste en anular todas las actualizaciones realizadas desde el inicio de la transaccin. El famoso RollBack se ejecuta automticamente en caso de producirse una excepcin, pero tambin podemos ejecutarlo de forma intencionada mediante la instruccin ttsabort.

Por supuesto podemos anidar transacciones de manera que se realizar el commit real en la base de datos cuando lleguemos al ttscommit de la transaccin de nivel superior. ttsbegin; .. . ttsbegin; ttscommit; // Aqu aun no se realiza el commit realmente .. . ttscommit; // Ahora si :) A medida que el interprete de Axapta va encontrando instrucciones ttsbegin va incrementando la variable global ttslevel y por cada ttscommit lo decrementa. Axapta comunica a la base de datos el commit real cuando ttslevel llega a 0. Para los ms curiosos tan solo decir que adems podis echar un vistazo a la clase Application, mtodos ttsNotifyBegin, ttsNotifyAbort y ttsNotifyCommit. Estas se llaman cada vez que ejecutamos un ttsbegin, ttsabort o ttscommit respectivamente para que Axapta realice una serie de notificaciones a dos sistemas de transacciones especiales de que dispone este ERP.

Bloqueos
Cuando se esta ejecutando simultneamente mas de un proceso, a veces sucede que los dos intentan modificar el mismo registro.

www.trucosaxapta.com Debido al uso de transacciones el sistema puede encontrarse con el problema de que un proceso (A) intenta modificar o leer un registro que ha sido modificado por otro proceso (B) cuya transaccin no ha finalizado. El problema est en que podra darse el caso de que esa transaccin no terminara de forma satisfactoria (commit) sino que tuvieran que anularse los cambios producidos en ese registro. Que se supone que debera hacer SQL cuando intentamos leer ese registro? Mostrar el valor anterior a la actualizacin producida por el proceso que est en curso (B)? Mostrar el valor modificado por el proceso (B)? En cualquiera de los 2 casos, y si falla el proceso (B), que valor dejamos en el registro cuando realicemos el rollback? Dejamos el valor anterior a la actualizacin producida por el proceso (B) a riesgo de que el proceso (A) haya modificado tambin este registro y machaquemos sus cambios? Imaginemos que se trata de un acumulado (del stock por ejemplo): El stock era 5, el proceso (B) ha restado una unidad y lo ha dejado a 4. El proceso (A) quera restar 2 unidades y basndose en el 4 lo ha dejado a 2. Si falla el proceso (B) y restaura el valor a 5 acabamos de destrozar el acumulado. Para solucionar este problema Sql-Server generar un bloqueo en el momento en que el proceso (B) modifique el registro de manera que el proceso (A) esperar a que (B) termine (bien o mal) para poder continuar. De esta forma nos aseguramos de que el proceso (A) se basar en datos correctos y no pondremos en peligro la consistencia de los mismos.

DeadLocks Imaginemos que el proceso (A) bloquea el registro n1, el proceso (B) bloquea el registro n2. Ahora el proceso (A) que prosigue su trabajo se dispone a modificar el registro n2, pero encuentra que esta bloqueado por el proceso (B). A su vez, el proceso (B) (por aquellas cosas del destino y de Murphy) se dispone a proseguir su trabajo pero necesita modificar el registro n1, que ah! Sorpresa! Est bloqueado por el proceso (A). En resumen : El proceso (A) est esperando a que finalice el proceso (B) para poder modificar el registro n 2 y el proceso (B) est esperando a que termine el proceso (A) para poder modificar el registro n1. Estamos frente a lo que se denomina DeadLock o lo que es lo mismo un bloqueo sin solucin. Normalmente Sql-Server detectar el problema, elegir uno de los dos procesos y lo cancelar. A veces no es capaz de detectarlo y se quedan bloqueados hasta que el usuario, el administrador o alguna otra circunstancia cancele uno de los procesos. Una posible solucin sera limitar el tiempo de espera para un bloqueo mediante el parmetro de SQL Lock_Timeout. El problema que nos podra ocasionar es que en el

www.trucosaxapta.com caso que no se tratase de un DeadLock si no de una espera un poco larga pero con final feliz, tambin generara un error y cancelara la transaccin.

Si nos fijamos, veremos que para evitar que dos procesos tengan que modificar el mismo registro, en Axapta casi no existen acumulados y contadores (secuencias numricas), y decimos casi porque hay casos en los que no tiene mas remedio que usarlos, pero en estos casos tienen una gestin especial para evitar DeadLocks.

Stocks Los stocks de inventario son un caso claro de acumulados. A partir de la Versin 3.0 de Axapta se ha aadido una funcionalidad llamada "transacciones mltiples de Inventario". Cuando est activada en lugar de acumular los movimientos de inventario directamente en el stock (tabla InventSum), los guarda en una tabla como operaciones pendientes de aplicar. Si la transaccin termina correctamente realiza la actualizacin del stock en los acumulados correspondientes.

ilustracin 1: En el men Administracin, Configurar, Sistema se encuentra esta opcin que permite activar o desactivar esta funcionalidad.

www.trucosaxapta.com Secuencias Numricas Para evitar los bloqueos, Axapta actualiza los contadores creando una transaccin en una conexin independiente, de esta forma no bloquea la secuencia numrica hasta que termina todo el proceso (sera un caos). Por este motivo si una secuencia numrica es de tipo continua (que no debe perder nmeros) el sistema almacena en una tabla a parte una lista de nmeros pendientes de determinar si se han asignado definitivamente o no. Si la transaccin finaliza correctamente estos nmeros quedarn marcados como asignados.

Escalado de Bloqueos SQL-Server mantiene una lista de los registros que se encuentran bloqueados en cualquier instante por todos los procesos que hay en ejecucin. Esto puede consumir bastante memoria. Para evitar el consumo excesivo de memoria, Sql-Server dispone de un mecanismo llamado Escalado de bloqueos. Este consiste en que en un momento determinado, SQL decide que si hay muchos registros bloqueados de una tabla, puede cambiar la lista de referencias a cada uno de esos registros por una sola referencia a nivel de pgina o bien a nivel de tabla segn el caso. Realmente puede ir escalando esta referencia incluso hasta llegar a nivel de Base de datos. Esto supone que puede bloquear toda una pgina o toda una tabla o toda la base de datos, lo que implica que por ahorrar consumo de memoria puede bloquear registros que no necesitaban ser bloqueados ya que no se han actualizado pero por desgracia se encontraban en una de las pginas que ha decidido

www.trucosaxapta.com bloquear o en la tabla etc.(Hay que sealar que el caso de bloqueo de Base de datos es un caso muy extremo y no suele darse) Este sistema a veces produce resultados indeseados. Por ejemplo en Axapta la tabla de pedidos de venta es comn para todas las empresas. Por lo tanto si una de ellas estuviese realizando un proceso de facturacin, sera posible que las dems no pudiesen modificar pedidos. Esto puede suceder si se tratan de facturas con muchas lneas, ya que Axapta crea una transaccin para cada factura. Para evitar este tipo de bloqueos lo mejor es realizar transacciones pequeas. Siempre y cuando sea posible (que en muchas ocasiones no lo es). Esto tiene truco Podemos desactivar el escalado de bloqueos en SQL-Server, existe un parmetro para hacerlo. Para introducirlo iremos a las propiedades de Sql-Server, solapa "General", Botn "Parmetros de Inicio", y aadimos el parmetro "T1211".

De todas formas debemos ser conscientes de lo que esto supone, estamos privando al servidor de esta funcionalidad, mediante la cual consigue liberar memoria cuando la necesita, lo que podra degradar el rendimiento. Aunque en sistemas con muchos usuarios y transacciones simultaneas puede acabar siendo necesario.

Tambin parece ser que es mejor disponer de un ndice con clave nica para que SqlServer pueda hacer referencia a los registros bloqueados. Si no es posible definir una clave nica, sera buena solucin crear un ndice por el "RecId".

Potrebbero piacerti anche