Вы находитесь на странице: 1из 13

TRANSACCIONES

EN SQL SERVER

Cncepto
Una
transaccin
en
un
Sistema de Gestin de Bases de Datos (SGBD), es un conjunto de
rdenes que se ejecutan formando una unidad de trabajo, es decir,
en forma indivisible o atmica.
Un SGBD se dice transaccional, si es capaz de mantener la
integridad de los datos, haciendo que estas transacciones no
puedan finalizar en un estado intermedio. Cuando por alguna causa
el sistema debe cancelar la transaccin, empieza a deshacer las
rdenes ejecutadas hasta dejar la base de datos en su estado inicial
(llamado punto de integridad), como si la orden de la transaccin
nunca se hubiese realizado.

Para esto, el lenguaje de consulta de datos SQL (Structured


Query Language), provee los mecanismos para especificar que
un conjunto de acciones deben constituir una transaccin.
BEGIN TRAN: Especifica que va a empezar una transaccin.
COMMIT TRAN: Le indica al motor que puede considerar la
transaccin completada con xito.
ROLLBACK TRAN: Indica que se ha alcanzado un fallo y que debe
restablecer la base al punto de integridad.
En un sistema ideal, las transacciones deberan garantizar todas
las propiedades ACID; en la prctica, a veces alguna de estas
propiedades se simplifica o debilita con vistas a obtener un
mejor rendimiento.

Atomicidad: es la propiedad que asegura que la operacin se ha


realizado o no, y por lo tanto ante un fallo del sistema no puede quedar a
medias.

Consistencia: Integridad. Es la propiedad que asegura que slo se


empieza aquello que se puede acabar. Por lo tanto se ejecutan aquellas
operaciones que no van a romper las reglas y directrices de integridad
de la base de datos.

Aislamiento: es la propiedad que asegura que una operacin no puede


afectar a otras. Esto asegura que la realizacin de dos transacciones
sobre la misma informacin sean independientes y no generen ningn
tipo de error.

Durabilidad: es la propiedad que asegura que una vez realizada la


operacin, sta persistir y no se podr deshacer aunque falle el
sistema.

Un ejemplo Bsico
de transaccin
Un ejemplo habitual de transaccin es el traspaso de una
cantidad de dinero entre cuentas bancarias. Normalmente se
realiza mediante dos operaciones distintas, una en la que se
decremento el saldo de la cuenta origen y otra en la que
incrementamos el saldo de la cuenta destino. Para garantizar la
atomicidad del sistema (es decir, para que no aparezca o
desaparezca dinero), las dos operaciones deben ser atmicas, es
decir, el sistema debe garantizar que, bajo cualquier
circunstancia (incluso una cada del sistema), el resultado final
es que, o bien se han realizado las dos operaciones, o bien no se
realizado ninguna.

Trabajaremos con la base de datos Northwind en nuestros ejemplos.


Vamos a realizar una transaccin que modifica el precio de dos productos
de la base de datos:
USE NorthWind
DECLARE @Error int
-- Declaramos una variable que utilizaremos para almacenar un
posible cdigo de error
BEGIN TRAN
BEGIN TRAN
--Iniciamos la transaccin
UPDATE Products SET UnitPrice=20 WHERE ProductName =Chai
--Ejecutamos la primera sentencia
SET @Error=@@ERROR
--Si ocurre un error almacenamos su cdigo en @Error
--y saltamos al trozo de cdigo que deshara la transaccin.
IF (@Error<>0) GOTO TratarError
--Si la primera sentencia se ejecuta con xito, pasamos a la segunda
UPDATE Products SET UnitPrice=20 WHERE ProductName=Chang
SET @Error=@@ERROR

-Y si hay un error hacemos como antes


IF (@Error<>0) GOTO TratarError
--Si llegamos hasta aqu es que los dos UPDATE se han completado
con
--xito y podemos "guardar" la transaccin en la base de datos
COMMIT TRAN
TratarError:
--Si ha ocurrido algn error llegamos hasta aqu
If @@Error<>0 THEN
BEGIN
PRINT Ha ecorrido un error. Abortamos la transaccin
--Se lo comunicamos al usuario y deshacemos la transaccin
--todo volver a estar como si nada hubiera ocurrido
ROLLBACK TRAN
END
Si tenemos dos sentencias dentro de una transaccin:
USE NorthWind
BEGIN TRAN
UPDATE Products SET UnitPrice=20 WHERE ProductName=Chang
UPDATE Products SET UnitPrice=20 WHERE ProductName=Chang
COMMIT TRAN

Estas dos sentencias se ejecutarn como una sola. Si por ejemplo en


medio de la transaccin (despus del primer update y antes del
segundo) hay un corte deelectricidad, cuando el SQL Server se
recupere se encontrar en medio de una transaccin y, o bien la
termina o bien la deshace, pero no se quedar a medias.
*El SQL Server slo se preocupa de ejecutar las sentencias, no de averiguar si
lo hacen correctamente o si lalgicade la transaccin es correcta. Eso es
cosa nuestra.

Transacciones Anidadas
Otra de las posibilidades que nos ofrece el SQL Server es utilizar
transacciones anidadas.
Esto quiere decir que podemos tener transacciones dentro de
transacciones, es decir, podemos empezar una nueva transaccin
sin haber terminado la anterior.

Asociada a esta idea de anidamiento existe una variable global


@@TRANCOUNT que tienevalor0 si no existe ningn nivel de
anidamiento, 1 si hay una transaccin anidada, 2 si estamos en el
segundo nivel de anidamiento y as sucesivamente.
La dificultad de trabajar con transacciones anidadas est en el
comportamientoque tienen ahora las sentencias COMMIT TRAN y
ROLLBACK TRAN.
ROLLBACK TRAN:Dentro de una transaccin anidada esta sentencia
deshace todas las transacciones internas hasta la instruccin BEGIN
TRANSACTION ms externa.
COMMIT TRAN:Dentro de una transaccin anidada esta sentencia
nicamente reduce en 1 el valor de @@TRANCOUNT, pero no "finaliza"
ninguna transaccin ni "guarda" los cambios. En el caso en el que
@@TRANCOUNT=1 (cuando estamos en la ltima transaccin)
COMMIT TRAN hace que todas las modificaciones efectuadas sobre los
datos desde el inicio de la transaccin sean parte permanente de la
base de datos, libera losrecursosmantenidos por la conexin y reduce
@@TRANCOUNT a 0.

CREATE TABLETest(Columna int)


GO
BEGIN TRAN TranExterna -- @@TRANCOUNT ahora es 1
SELECT El nivel de anidamiento es, @@TRANCOUNT
INSERT INTO Test VALUES (1)
BEGIN TRAN TranInterna1 -- @@TRANCOUNT ahora es 2.
SELECT El nivel de anidamiento es, @@TRANCOUNT
INSERT INTO Test VALUES (2)
BEGIN TRAN TranInterna2 -- @@TRANCOUNT ahora es 3.
SELECT El nivel de anidamiento es, @@TRANCOUNT
INSERT INTO Test VALUES (3)
COMMIT TRAN TranInterna2 -- Reduce @@TRANCOUNT a 2.
-- Pero no se guarda nada en la base de datos.
SELECT El nivel de anidamiento es, @@TRANCOUNT
COMMIT TRAN TranInterna1 -- Reduce @@TRANCOUNT a 1.
-- Pero no se guarda nada en la base de datos.
SELECT El nivel de anidamiento es, @@TRANCOUNT
COMMIT TRAN TranExterna -- Reduce @@TRANCOUNT a 0.
-- Se lleva a cabo la transaccin externa y todo lo que conlleva.

SELECT El nivel de anidamiento es, @@TRANCOUNT


SELECT * FROM Test
Por cierto que lo de usar nombre para las transacciones es por claridad,
puesto que COMMIT TRAN como ya hemos dicho solamente reduce en
1 el valor de @@TRANCOUNT.
Veamos ahora un ejemplo de transaccin anidada con ROLLBACK TRAN
BEGIN TRAN TranExterna -- @@TRANCOUNT ahora es 1
SELECT 'El nivel de anidamiento es', @@TRANCOUNT
INSERT INTO Test VALUES (1)
BEGIN TRAN TranInterna1 -- @@TRANCOUNT ahora es 2.
SELECT 'El nivel de anidamiento es', @@TRANCOUNT
INSERT INTO Test VALUES (2)
BEGIN TRAN TranInterna2 -- @@TRANCOUNT ahora es 3.
SELECT 'El nivel de anidamiento es', @@TRANCOUNT
INSERT INTO Test VALUES (3)
ROLLBACK TRAN --@@TRANCOUNT es 0 y se deshace

la transaccin externa y todas las internas


SELECT 'El nivel de anidamiento es', @@TRANCOUNT
SELECT * FROM Test
En este caso no se inserta nada puesto que el ROLLBACK TRAN deshace todas
las
transacciones dentro de nuestro anidamiento hasta la transaccin ms externa
y
adems hace @@TRANCOUNT=0

SAVE TRAN
Esta sentencia crea un punto dealmacenamientodentro de una
transaccin. Estamarcasirve para deshacer una transaccin en
curso slo hasta ese punto. Por supuesto nuestra transaccin
debe continuar y terminar con un COMMIN TRAN (o los que
hagan falta) para que todo se guarde o con un ROLLBACK TRAN
para volver al estado previo al primer BEGIN TRAN.
BEGIN TRAN TranExterna -- @@TRANCOUNT ahora es 1
SELECT 'El nivel de anidamiento es', @@TRANCOUNT
INSERT INTO Test VALUES (1)
BEGIN TRAN TranInterna1 -- @@TRANCOUNT ahora es 2.

SELECT 'El nivel de anidamiento es', @@TRANCOUNT


INSERT INTO Test VALUES (2)
SAVE TRAN Guadada
BEGIN TRAN TranInterna2 -- @@TRANCOUNT ahora es 3.
SELECT 'El nivel de anidamiento es', @@TRANCOUNT
INSERT INTO Test VALUES (3)
ROLLBACK TRAN Guadada -- se deshace lo hecho el
punto guardado.
SELECT 'El nivel de anidamiento es', @@TRANCOUNT
--Ahora podemos decidir si la transaccin se lleva a cabo
--o se deshace completamente
--Para deshacerla un ROLLBACK bastar como hemos
visto
--Pero para guardar la transaccin hace falta reducir
@@TRANCOUNT a 0

COMMIT TRAN TranInterna1 -- Reduce @@TRANCOUNT a


2.
SELECT 'El nivel de anidamiento es', @@TRANCOUNT
COMMIT TRAN TranInterna1 -- Reduce @@TRANCOUNT a
1.
-- Pero no se guarda nada en la base de datos.
SELECT 'El nivel de anidamiento es', @@TRANCOUNT
COMMIT TRAN TranExterna -- Reduce @@TRANCOUNT a 0.
-- Se lleva a cabo la transaccin externa y todo lo que
conlleva.
SELECT 'El nivel de anidamiento es', @@TRANCOUNT
SELECT * FROM Test
Si no ponemos el nombre del punto salvado con SAVE
TRAN al hacer un ROLLBACK TRAN se deshace la
transaccin ms externa y @@TRANCOUNT se pone a 0.

Вам также может понравиться