Pregunta 1¿Cuál es el nombre de la propiedad que trata los dos UPDATEs (débito + crédito) de una transferencia de dinero como una sola unidad, confirmándolos juntos si ambos tienen éxito o deshaciendo ambos si algo falla a mitad?
Transacciones y bloqueos
Recorre la atomicidad con BEGIN/COMMIT/ROLLBACK, el rollback parcial con SAVEPOINT, AUTOCOMMIT, y los conceptos de bloqueos, niveles de aislamiento y las propiedades ACID, todo con diagramas y ejemplos de código de solo lectura.
Este artículo se construye sobre diagramas y código de solo lectura
Las transacciones solo cobran vida realmente sobre un RDBMS real donde múltiples usuarios acceden a la base de datos al mismo tiempo, y la consola en el navegador de este curso no puede reproducir fielmente ese comportamiento.
Por eso este artículo no tiene ejercicios ejecutables: lee los bloques de code de cada sección como ejemplos pensados para ejecutarse en un RDBMS real (MySQL / PostgreSQL / Oracle, etc.).
Qué es una transacción — tratar varias sentencias SQL como una sola unidad
Una transacción es una forma de tratar varias sentencias SQL como una sola unidad: si todas tienen éxito, se confirman juntas; si algo sale mal a mitad de camino, todas se revierten juntas.
Es esencial para cualquier proceso donde tener éxito solo en la mitad del trabajo sería un problema: piensa en transferencias bancarias (un UPDATE para debitar, uno para acreditar), o confirmar un pedido en línea (decrementar inventario, insertar la fila del pedido).
La forma básica es BEGIN; (iniciar) → varias sentencias → COMMIT; (confirmar) / ROLLBACK; (deshacer).
Los bloques de code en este artículo usan una tabla account que representa cuentas bancarias. Las tres columnas son account_id, owner (nombre del titular de la cuenta) y balance. Asume los siguientes datos iniciales mientras lees.
| account_id | owner | balance |
|---|---|---|
| 1 | Alice | 1000 |
| 2 | Bob | 500 |
| 3 | Carol | 800 |
| 4 | Dave | 1200 |
Atomicidad — BEGIN ... COMMIT / ROLLBACK
Cuando haces BEGIN; y luego COMMIT;, cada cambio entre esas dos sentencias se aplica junto.
Ejecuta ROLLBACK; en lugar de eso y cada cambio después de BEGIN; se deshace, dejando la base de datos en su estado anterior al inicio de la transacción.
Esta propiedad de "todo o nada" se llama atomicidad: una unidad que no se puede dividir en piezas más pequeñas.
Cuando algo como una violación de restricción CHECK sale mal a mitad de la transacción, el movimiento estándar es ROLLBACK; para desarmar todo de forma segura.
-- Transferencia: Alice -> Bob, 100 (pensado para correr en un RDBMS real)
BEGIN;
UPDATE account SET balance = balance - 100 WHERE owner = 'Alice';
UPDATE account SET balance = balance + 100 WHERE owner = 'Bob';
COMMIT; -- ambos UPDATEs se confirman en el mismo instante
-- Deshacer: cambiamos de opinión / algo salió mal
BEGIN;
UPDATE account SET balance = balance - 300 WHERE owner = 'Alice';
UPDATE account SET balance = balance + 300 WHERE owner = 'Bob';
ROLLBACK; -- ambos UPDATEs se descartan juntos
SAVEPOINT — revertir solo parte de una transacción
SAVEPOINT name; coloca un marcador a mitad de camino dentro de una transacción, y ROLLBACK TO name; revierte solo hasta ese marcador.
Los cambios hechos antes del marcador se mantienen, así que puedes seguir con otras operaciones y hacer COMMIT; al final.
Un uso típico: un proceso en varios pasos como "confirmar pedido → otorgar puntos → decrementar inventario", donde solo falló el decremento de inventario y quieres reintentar solo ese paso. Es más granular que tirar toda la transacción con ROLLBACK;.
-- Deshacer solo la segunda actualización con SAVEPOINT (pensado para correr en un RDBMS real)
BEGIN;
UPDATE account SET balance = balance - 100 WHERE owner = 'Carol';
SAVEPOINT sp1;
UPDATE account SET balance = balance - 100 WHERE owner = 'Dave';
ROLLBACK TO sp1; -- deshace solo lo de Dave (Carol -100 se mantiene)
COMMIT; -- confirma solo Carol -100
AUTOCOMMIT — por defecto, cada sentencia se confirma sola
Cuando ejecutas un UPDATE o INSERT independiente sin escribir BEGIN; antes, cada sentencia se confirma automáticamente por sí misma.
Eso se llama AUTOCOMMIT: el modo por defecto en el que cada sentencia se confirma en cuanto se ejecuta.
Para confirmar o deshacer varias sentencias como una sola unidad, tienes que iniciar explícitamente una transacción con BEGIN;.
Bloqueos e interbloqueos — fundamentos de concurrencia
Las bases de datos del mundo real reciben acceso de muchos usuarios al mismo tiempo. Digamos que Alice tiene un saldo de 1000, y dos tiendas (X e Y) intentan cobrarle en el mismo instante: ambas podrían leer "1000" y restar de ese valor, y uno de esos débitos desaparece silenciosamente.
La defensa contra esto es un bloqueo (lock): mientras la transacción de un usuario toca una fila, cualquier otro que intente tocar la misma fila tiene que esperar. El primero en entrar bloquea la fila, y el segundo espera.
Pero hay un lado opuesto: si el usuario A bloquea cuentas en el orden "cuenta 1 → cuenta 2" y el usuario B las bloquea en el orden "cuenta 2 → cuenta 1", terminan esperando los bloqueos del otro para siempre. Eso es un interbloqueo (deadlock). El arreglo clásico es adquirir siempre los bloqueos en el mismo orden (por ejemplo, siempre por account_id ascendente). Si ocurre un interbloqueo, la base de datos abortará a la fuerza una de las transacciones para romper el ciclo.
Niveles de aislamiento y ACID — repaso de terminología
Un nivel de aislamiento controla cuánto del trabajo en progreso de otras transacciones concurrentes puede ver una transacción dada.
Los ajustes más débiles (como READ COMMITTED) son más rápidos pero te dejan ver más de los cambios de otros, mientras que los más fuertes (como SERIALIZABLE) son más seguros pero fuerzan más espera.
Junto con la atomicidad (A), la consistencia (C), el aislamiento (I) y la durabilidad (D — una vez que ocurre un COMMIT, los datos quedan en disco y sobreviven a caídas o cortes de luz), estas cuatro conforman las propiedades ACID.
El comportamiento exacto de los bloqueos y los niveles de aislamiento varía según el producto, así que cuando construyas algo para producción, revisa las especificaciones de la base de datos que estás usando.
| ACID | Significado |
|---|---|
| A — Atomicidad | Las sentencias entre BEGIN y COMMIT o se aplican todas o ninguna. |
| C — Consistencia | Las restricciones CHECK, las claves foráneas y otras reglas de integridad se mantienen antes y después de la transacción. |
| I — Aislamiento | El trabajo en progreso de otras transacciones concurrentes queda oculto según el nivel de aislamiento. |
| D — Durabilidad | Un resultado confirmado queda en disco y sobrevive a cortes de luz o caídas. |
Verificación de conocimientos
Responde cada pregunta una a una.
Pregunta 2¿Qué le ocurre a la tabla cuando ejecutas BEGIN; UPDATE ...; UPDATE ...; ROLLBACK;?
Pregunta 3¿Qué pasa cuando ejecutas un solo UPDATE por sí mismo, sin escribir BEGIN; antes?