COMMIT y ROLLBACK
COMMIT confirma todos los cambios realizados dentro de una transacción. ROLLBACK revierte todos los cambios y restaura los datos a su estado anterior.
START TRANSACTION
Inicia una transacción explícita. Todas las sentencias posteriores forman parte de la transacción hasta que se ejecute COMMIT o ROLLBACK.
-- Estas tres formas son equivalentes
START TRANSACTION;
BEGIN;
BEGIN WORK;COMMIT
Confirma permanentemente todos los cambios realizados en la transacción.
START TRANSACTION;
INSERT INTO productos (nombre, precio, stock, categoria_id)
VALUES ('Producto de prueba', 99.99, 10, 1);
-- Los cambios se hacen permanentes
COMMIT;
-- Verificar
SELECT * FROM productos WHERE nombre = 'Producto de prueba';| id | nombre | precio | stock | categoria_id |
|---|---|---|---|---|
| ... | Producto de prueba | 99.99 | 10 | 1 |
-- Limpieza
DELETE FROM productos WHERE nombre = 'Producto de prueba';ROLLBACK
Revierte todos los cambios realizados en la transacción.
-- Ver stock actual
SELECT id, nombre, stock FROM productos WHERE id = 1;| id | nombre | stock |
|---|---|---|
| 1 | iPhone 15 Pro | 50 |
START TRANSACTION;
UPDATE productos SET stock = 0 WHERE id = 1;
-- Verificar el cambio (dentro de la transacción)
SELECT stock FROM productos WHERE id = 1;| stock |
|---|
| 0 |
-- Revertir
ROLLBACK;
-- El stock vuelve al valor original
SELECT stock FROM productos WHERE id = 1;| stock |
|---|
| 50 |
Visibilidad de los cambios
Los cambios dentro de una transacción solo son visibles para la conexión que los realiza, hasta que se confirmen con COMMIT. Este comportamiento depende del nivel de aislamiento configurado.
Conexión 1:
START TRANSACTION;
UPDATE productos SET precio = 999.99 WHERE id = 1;
-- El precio cambió para esta conexión
SELECT precio FROM productos WHERE id = 1;
-- Resultado: 999.99Conexión 2 (simultánea):
-- Ve el precio original (la transacción no se ha confirmado)
SELECT precio FROM productos WHERE id = 1;
-- Resultado: 1299.99Conexión 1:
COMMIT;
-- Ahora el cambio es visible para todosEjemplo: transferencia de fondos
CREATE TABLE cuentas (
id INT AUTO_INCREMENT PRIMARY KEY,
titular VARCHAR(100),
saldo DECIMAL(10,2)
);
INSERT INTO cuentas (titular, saldo)
VALUES ('Alicia', 1000.00), ('Roberto', 500.00);DELIMITER //
CREATE PROCEDURE sp_transferir(
IN p_origen INT,
IN p_destino INT,
IN p_monto DECIMAL(10,2)
)
BEGIN
DECLARE v_saldo DECIMAL(10,2);
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
ROLLBACK;
SELECT 'Error: transferencia cancelada' AS resultado;
END;
START TRANSACTION;
-- Verificar saldo (FOR UPDATE bloquea la fila)
SELECT saldo INTO v_saldo
FROM cuentas WHERE id = p_origen
FOR UPDATE;
IF v_saldo < p_monto THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'Saldo insuficiente';
END IF;
-- Debitar origen
UPDATE cuentas SET saldo = saldo - p_monto WHERE id = p_origen;
-- Acreditar destino
UPDATE cuentas SET saldo = saldo + p_monto WHERE id = p_destino;
COMMIT;
SELECT 'Transferencia exitosa' AS resultado;
END //
DELIMITER ;-- Transferir 200 de Alicia a Roberto
CALL sp_transferir(1, 2, 200.00);| resultado |
|---|
| Transferencia exitosa |
SELECT * FROM cuentas;| id | titular | saldo |
|---|---|---|
| 1 | Alicia | 800.00 |
| 2 | Roberto | 700.00 |
-- Intentar transferir más de lo disponible
CALL sp_transferir(1, 2, 5000.00);| resultado |
|---|
| Error: transferencia cancelada |
-- Los saldos no cambiaron
SELECT * FROM cuentas;| id | titular | saldo |
|---|---|---|
| 1 | Alicia | 800.00 |
| 2 | Roberto | 700.00 |
COMMIT y ROLLBACK con autocommit
Cuando autocommit = 1 (predeterminado), cada sentencia individual se confirma automáticamente. Para agrupar sentencias, usa START TRANSACTION. Puedes ver cómo funciona el autocommit en la introducción a las transacciones:
-- Con autocommit activado
-- Este INSERT se confirma automáticamente
INSERT INTO productos (nombre, precio, stock, categoria_id)
VALUES ('Auto 1', 10.00, 1, 1);
-- Pero dentro de una transacción explícita, no
START TRANSACTION;
INSERT INTO productos (nombre, precio, stock, categoria_id)
VALUES ('Auto 2', 20.00, 1, 1);
ROLLBACK;
-- 'Auto 1' existe, 'Auto 2' no-- Limpieza
DELETE FROM productos WHERE nombre IN ('Auto 1', 'Auto 2');Desactivar autocommit
-- Desactivar autocommit para la sesión
SET autocommit = 0;
INSERT INTO productos (nombre, precio, stock, categoria_id)
VALUES ('Manual 1', 10.00, 1, 1);
INSERT INTO productos (nombre, precio, stock, categoria_id)
VALUES ('Manual 2', 20.00, 1, 1);
-- Nada se ha confirmado aún
-- Necesitas COMMIT explícito
COMMIT;
-- Reactivar autocommit
SET autocommit = 1;-- Limpieza
DELETE FROM productos WHERE nombre IN ('Manual 1', 'Manual 2');ROLLBACK parcial con SAVEPOINT
Para revertir solo parte de una transacción, usa SAVEPOINT:
START TRANSACTION;
INSERT INTO productos (nombre, precio, stock, categoria_id)
VALUES ('Paso 1', 10.00, 1, 1);
SAVEPOINT sp1;
INSERT INTO productos (nombre, precio, stock, categoria_id)
VALUES ('Paso 2', 20.00, 1, 1);
-- Revertir solo el paso 2
ROLLBACK TO sp1;
COMMIT;
-- Solo 'Paso 1' se guardó-- Limpieza
DELETE FROM productos WHERE nombre LIKE 'Paso%';Los SAVEPOINTs se cubren en detalle en el siguiente artículo.
Errores comunes
ROLLBACK sin transacción activa
-- Sin START TRANSACTION, ROLLBACK no tiene efecto
INSERT INTO productos (nombre, precio, stock, categoria_id)
VALUES ('Ya confirmado', 10.00, 1, 1);
ROLLBACK; -- No revierte nada (autocommit ya confirmó el INSERT)DELETE FROM productos WHERE nombre = 'Ya confirmado';DDL dentro de transacciones
START TRANSACTION;
INSERT INTO productos (nombre, precio, stock, categoria_id)
VALUES ('DDL test', 10.00, 1, 1);
-- CREATE TABLE causa COMMIT implícito
CREATE TABLE temp_ddl (id INT);
-- El INSERT ya fue confirmado, ROLLBACK no lo revierte
ROLLBACK;
SELECT * FROM productos WHERE nombre = 'DDL test';
-- El registro existe-- Limpieza
DROP TABLE IF EXISTS temp_ddl;
DELETE FROM productos WHERE nombre = 'DDL test';Limpieza
DROP PROCEDURE IF EXISTS sp_transferir;
DROP TABLE IF EXISTS cuentas;Las transacciones son la base de cualquier sistema que gestione operaciones de negocio críticas: transferencias, pedidos, facturación. En Andorra Dev diseñamos CRMs y ERPs donde cada operación financiera se ejecuta dentro de transacciones MySQL para garantizar la integridad de los datos.
En el siguiente artículo veremos SAVEPOINT para crear puntos de restauración dentro de una transacción.
Escrito por Eduardo Lázaro
