Trescientos euros que desaparecen
Trabajas en una aplicación de pagos. Elena envía 300 € a Raúl.
El programa resta 300 € de la cuenta de Elena. Justo después, el servidor se reinicia.
Elena ya no tiene ese dinero y Raúl no lo ha recibido. Para un banco, ese es el peor fallo posible. Las transacciones existen para que no ocurra.
Al final de esta lección
Nota
Puedo explicar por qué una transferencia tiene que ser todo o nada.
Palabras clave
| Palabra | Qué significa | Ejemplo |
|---|---|---|
| Transacción | un grupo de cambios que se guardan juntos o no se guardan | |
| BEGIN | abre una transacción | |
| COMMIT | confirma los cambios y los hace definitivos | |
| ROLLBACK | deshace todos los cambios desde BEGIN | |
| UPDATE | cambia valores de filas que ya existen | UPDATE accounts SET balance = 200 |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.
Una transferencia son dos escrituras
Mover dinero exige dos cambios: restar en una cuenta y sumar en la otra.
Entre los dos cambios hay un momento en que el dinero no está en ningún sitio. Si algo falla justo ahí, el total de las cuentas ya no cuadra.
La tabla de abajo enseña ese momento. Nadie debería verlo nunca.
Ejemplo: los saldos paso a paso
| Momento | Elena | Raúl | Total |
|---|---|---|---|
| Antes | 500 € | 100 € | 600 € |
| Después de restar | 200 € | 100 € | 300 € |
| Después de sumar | 200 € | 400 € | 600 € |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.
BEGIN y COMMIT guardan todo junto
BEGIN abre una transacción. Los cambios que siguen quedan pendientes.
COMMIT los confirma todos a la vez. Hasta ese momento, nadie más ve los cambios a medias.
Si el servidor se cae antes del COMMIT, la base de datos descarta lo pendiente al arrancar. Nunca se queda con la mitad.
Prueba: una transferencia confirmada
-- Elena paga 300 euros a Raúl.
BEGIN;
UPDATE accounts SET balance = balance - 300 WHERE id = 1;
UPDATE accounts SET balance = balance + 300 WHERE id = 2;
COMMIT;
-- Los dos saldos han cambiado y el total sigue siendo 600.
SELECT owner, balance FROM accounts;
SELECT SUM(balance) AS total FROM accounts;
ROLLBACK lo deshace todo
A veces la aplicación ve un problema a mitad: no hay saldo, o la cuenta de destino está bloqueada.
Entonces envía ROLLBACK. La base de datos deshace todos los cambios desde BEGIN.
Las cuentas vuelven a estar como antes, como si la transferencia no hubiera empezado.
Prueba: una transferencia anulada
-- La misma transferencia, pero algo va mal a mitad.
BEGIN;
UPDATE accounts SET balance = balance - 300 WHERE id = 1;
-- Aquí la aplicación detecta un error y lo anula todo.
ROLLBACK;
-- Elena sigue teniendo 500 euros.
SELECT owner, balance FROM accounts;
-- Cambia ROLLBACK por COMMIT y vuelve a ejecutar. ¿Adónde van los 300 euros?
Un error frecuente
Advertencia
Mucha gente cree que, si algo falla, la base de datos lo deshace sola. Solo lo hace dentro de una transacción. Sin BEGIN, cada UPDATE se guarda en cuanto termina, y el primero se queda aunque falle el segundo.