Transacciones en SQL
Aprende qué son las transacciones en SQL, cómo funcionan y cómo utilizarlas para mantener la integridad de los datos en operaciones complejas.
Cristian Escalante
Última actualización: 11 de mayo de 2025
¿Qué son las transacciones en SQL?
Una transacción en SQL es una secuencia de operaciones que se ejecutan como una única unidad de trabajo. Si todas las operaciones dentro de la transacción se completan correctamente, los cambios se guardan permanentemente en la base de datos (commit). Si alguna operación falla, todos los cambios realizados dentro de la transacción se revierten (rollback).
Las transacciones son fundamentales para mantener la integridad de los datos en operaciones que involucran múltiples cambios relacionados entre sí.
Componentes básicos de una transacción
Una transacción típica consta de los siguientes elementos:
- BEGIN TRANSACTION: Marca el inicio de la transacción.
- Operaciones SQL: Conjunto de instrucciones SQL (INSERT, UPDATE, DELETE) que se ejecutarán como parte de la transacción.
- COMMIT: Confirma y guarda todos los cambios realizados durante la transacción.
- ROLLBACK: Revierte todos los cambios realizados durante la transacción en caso de error.
Sintaxis básica
-- Iniciar una transacción
BEGIN TRANSACTION;
-- Operaciones SQL
UPDATE cuentas SET saldo = saldo - 1000 WHERE id_cuenta = 1;
UPDATE cuentas SET saldo = saldo + 1000 WHERE id_cuenta = 2;
-- Si todo está correcto, confirmar los cambios
COMMIT;
-- Si hay un error, deshacer los cambios
-- ROLLBACK;
Ejemplo práctico: Transferencia bancaria
Imaginemos una transferencia de dinero entre dos cuentas bancarias. Esta operación debe ser atómica: o se completa en su totalidad o no se realiza ningún cambio.
BEGIN TRANSACTION;
-- Verificar si la cuenta origen tiene saldo suficiente
DECLARE @saldo_disponible DECIMAL(10,2);
SELECT @saldo_disponible = saldo FROM cuentas WHERE id_cuenta = 1;
IF @saldo_disponible >= 1000
BEGIN
-- Restar dinero de la cuenta origen
UPDATE cuentas SET saldo = saldo - 1000 WHERE id_cuenta = 1;
-- Sumar dinero a la cuenta destino
UPDATE cuentas SET saldo = saldo + 1000 WHERE id_cuenta = 2;
-- Registrar la transferencia
INSERT INTO transferencias (cuenta_origen, cuenta_destino, monto, fecha)
VALUES (1, 2, 1000, GETDATE());
COMMIT;
PRINT 'Transferencia completada con éxito';
END
ELSE
BEGIN
ROLLBACK;
PRINT 'Saldo insuficiente para realizar la transferencia';
END
Savepoints (puntos de guardado)
Los savepoints permiten crear puntos de control dentro de una transacción, lo que posibilita revertir parte de la transacción sin necesidad de deshacer toda la operación.
BEGIN TRANSACTION;
INSERT INTO clientes (nombre, email) VALUES ('Ana López', 'ana@ejemplo.com');
SAVE TRANSACTION punto1;
UPDATE productos SET stock = stock - 5 WHERE id_producto = 101;
-- Si hay un problema con la actualización de stock
-- ROLLBACK TRANSACTION punto1; -- Revierte solo hasta el punto de guardado
-- Si todo está bien
COMMIT;
Control de errores en transacciones
Es importante manejar adecuadamente los errores dentro de las transacciones:
BEGIN TRY
BEGIN TRANSACTION;
-- Operaciones SQL
UPDATE cuentas SET saldo = saldo - 1000 WHERE id_cuenta = 1;
UPDATE cuentas SET saldo = saldo + 1000 WHERE id_cuenta = 2;
COMMIT;
END TRY
BEGIN CATCH
ROLLBACK;
-- Registrar el error
INSERT INTO log_errores (mensaje, fecha)
VALUES (ERROR_MESSAGE(), GETDATE());
-- Reenviar el error para que sea manejado por la aplicación
THROW;
END CATCH
Niveles de aislamiento de transacciones
SQL proporciona diferentes niveles de aislamiento que determinan cómo interactúan las transacciones concurrentes:
- READ UNCOMMITTED: Permite leer datos no confirmados (dirty reads).
- READ COMMITTED: Solo permite leer datos confirmados (comportamiento predeterminado en muchos SGBD).
- REPEATABLE READ: Garantiza que las lecturas repetidas dentro de una transacción devuelvan los mismos resultados.
- SERIALIZABLE: El nivel más estricto, garantiza que las transacciones se comporten como si se ejecutaran en serie.
-- Establecer el nivel de aislamiento
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
BEGIN TRANSACTION;
-- Operaciones SQL
COMMIT;
Transacciones implícitas vs. explícitas
- Transacciones explícitas: Son aquellas que iniciamos manualmente con BEGIN TRANSACTION y finalizamos con COMMIT o ROLLBACK.
- Transacciones implícitas: Algunas operaciones SQL individuales se ejecutan automáticamente como transacciones, incluso sin un BEGIN TRANSACTION explícito.
-- Activar transacciones implícitas
SET IMPLICIT_TRANSACTIONS ON;
-- A partir de aquí, cada instrucción SQL inicia una transacción implícita
UPDATE productos SET precio = precio * 1.05;
COMMIT; -- Debemos confirmar explícitamente
-- Desactivar transacciones implícitas
SET IMPLICIT_TRANSACTIONS OFF;
Diferencias entre sistemas de gestión de bases de datos
La sintaxis y características de las transacciones pueden variar según el sistema de gestión de bases de datos:
MySQL
START TRANSACTION;
-- Operaciones SQL
COMMIT;
-- o
ROLLBACK;
PostgreSQL
BEGIN;
-- Operaciones SQL
COMMIT;
-- o
ROLLBACK;
Oracle
-- Las transacciones comienzan implícitamente
-- Operaciones SQL
COMMIT;
-- o
ROLLBACK;
SQL Server
BEGIN TRANSACTION;
-- Operaciones SQL
COMMIT TRANSACTION;
-- o
ROLLBACK TRANSACTION;
Mejores prácticas
- Mantén las transacciones cortas: Las transacciones largas pueden bloquear recursos y afectar el rendimiento.
- Evita operaciones de E/S o llamadas externas: Estas operaciones pueden ser lentas y aumentar la duración de la transacción.
- Maneja adecuadamente los errores: Utiliza bloques TRY-CATCH para asegurar que se realice ROLLBACK en caso de error.
- Considera el nivel de aislamiento: Elige el nivel adecuado según tus necesidades de consistencia y rendimiento.
- Evita transacciones anidadas complejas: Pueden ser difíciles de depurar y mantener.
Conclusión
Las transacciones son un mecanismo fundamental para garantizar la integridad de los datos en operaciones complejas. Proporcionan atomicidad, consistencia, aislamiento y durabilidad (propiedades ACID) a las operaciones de la base de datos, asegurando que los datos permanezcan en un estado coherente incluso en caso de fallos del sistema o errores en la aplicación.