transacciones-sql-server

Transacciones en SQL Server

  • 4 min

Hasta ahora, cada vez que hemos ejecutado un INSERT, UPDATE o DELETE, la operación se ha confirmado inmediatamente. Si la línea de código no daba error, el cambio se guardaba en piedra al instante.

Pero el mundo real es complejo. A menudo, una operación de negocio implica varios pasos en la base de datos.

El ejemplo clásico: Una transferencia bancaria.

  1. Restamos 100€ de la cuenta de Ana.
  2. Sumamos 100€ a la cuenta de Beto.

¿Qué pasa si se va la luz justo después del paso 1 y antes del paso 2? Que Ana ha perdido su dinero, Beto no lo ha recibido, y el banco tiene un descuadre contable grave.

Como eso sería un problemon, para evitar eso usamos las Transacciones.

¿Qué es una Transacción?

Una transacción es una unidad lógica de trabajo que agrupa una o más operaciones. Su objetivo principal es garantizar la propiedad de Atomicidad (la ‘A’ de ACID):

Atomicidad: O se ejecutan todas las operaciones del grupo con éxito, o no se ejecuta ninguna.

No existen estados intermedios. Si algo falla a mitad de camino, la base de datos debe ser capaz de “viajar en el tiempo” hacia atrás y dejar todo exactamente como estaba al principio.

Los comandos de control

En T-SQL, controlamos las transacciones explícitas con tres comandos fundamentales:

El comando BEGIN TRANSACTION inicia una nueva transacción. A partir de este punto, todas las operaciones realizadas en la base de datos forman parte de la transacción.

BEGIN TRANSACTION;
Copied!

El comando COMMIT finaliza la transacción y confirma todos los cambios realizados. Una vez confirmada, los cambios son permanentes y no se pueden deshacer.

COMMIT;
Copied!

El comando ROLLBACK deshace todos los cambios realizados desde el inicio de la transacción. Esto es útil si ocurre un error y se necesita revertir las operaciones.

ROLLBACK;
Copied!

Vamos a ver cómo implementaríamos el ejemplo del banco de forma segura.

-- Iniciamos la transacción
BEGIN TRANSACTION;

-- Paso 1: Restar dinero a Ana
UPDATE Cuentas 
SET Saldo = Saldo - 100 
WHERE Cliente = 'Ana';

-- Imaginemos que aquí ocurre un error o se va la luz.
-- Como no hemos hecho COMMIT, SQL Server desharía el paso 1 automáticamente al reiniciar.

-- Paso 2: Sumar dinero a Beto
UPDATE Cuentas 
SET Saldo = Saldo + 100 
WHERE Cliente = 'Beto';

-- Si llegamos hasta aquí sin errores, guardamos todo
COMMIT TRANSACTION;
Copied!

El uso del ROLLBACK

El ROLLBACK es nuestro botón de “Deshacer”. Podemos invocarlo manualmente si detectamos una condición lógica que impide continuar.

Por ejemplo, ¿qué pasa si Ana no tiene saldo suficiente?

BEGIN TRANSACTION;

    -- Paso 1: Intentamos restar
    UPDATE Cuentas 
    SET Saldo = Saldo - 100 
    WHERE Cliente = 'Ana';

    -- Verificamos si la cuenta se ha quedado en negativo
    DECLARE @NuevoSaldo DECIMAL(10,2);
    SELECT @NuevoSaldo = Saldo FROM Cuentas WHERE Cliente = 'Ana';

    IF @NuevoSaldo < 0
    BEGIN
        -- ¡Problema! No tiene fondos. Deshacemos todo.
        PRINT 'Error: Fondos insuficientes. Cancelando operación.';
        ROLLBACK TRANSACTION;
    END
    ELSE
    BEGIN
        -- Todo correcto, procedemos con el ingreso a Beto
        UPDATE Cuentas 
        SET Saldo = Saldo + 100 
        WHERE Cliente = 'Beto';
        
        -- Confirmamos la transacción
        COMMIT TRANSACTION;
        PRINT 'Transferencia realizada con éxito.';
    END
Copied!

En este script, si Ana se queda en negativo, el UPDATE inicial se revierte gracias al ROLLBACK. Es como si nunca hubiera ocurrido.

Transacciones Implícitas vs Explícitas

Es importante entender cómo funciona SQL Server por defecto:

  • Auto-Commit (Por defecto): Cada instrucción individual (INSERT, UPDATE…) es una transacción en sí misma. Si ejecutas una línea y funciona, se guarda (COMMIT automático). Si falla, se deshace (ROLLBACK automático).
  • Transacción Explícita: En cuanto escribimos BEGIN TRANSACTION, desactivamos el auto-commit para esa sesión hasta que cerramos la transacción.

¡Cuidado con dejar transacciones abiertas! Una de las causas más comunes de que una base de datos se “cuelgue” es un desarrollador que ejecutó BEGIN TRAN, hizo unos cambios, y se fue a comer sin ejecutar COMMIT o ROLLBACK.

Mientras la transacción está abierta, SQL Server bloquea las filas (o tablas) afectadas para protegerlas. Nadie más podrá leer ni escribir en ellas hasta que tú termines. Cierra siempre lo que abres.

@@TRANCOUNT

Si alguna vez no estás seguro de si tienes una transacción abierta, puedes consultar la variable del sistema @@TRANCOUNT.

  • Si devuelve 0: No hay transacción activa.
  • Si devuelve > 0: Hay una transacción activa (el número indica el nivel de anidamiento).
SELECT @@TRANCOUNT;
Copied!