💾Qué son las transacciones ACID y por qué siguen importando


🗒️Repaso: propiedades ACID en bases de datos
Lo primero que debemos aclarar es que ACID no son propiedades de la base de datos en sí, sino de las transacciones que esta gestiona. Una transacción en una base de datos es una secuencia de operaciones que podemos tratar como una sola unidad indivisible. Pues bien, las transacciones ACID van a cumplir con las siguientes propiedades:
🟣Atomicidad (atomicity)
Cuando se ejecuta una transacción, esta va a ser realizada por completo. Si no es ejecutada por completo por algún problema, entonces será rechazada y revertida. Por lo tanto, si tenemos que una operación dentro de nuestra transacción falla, cada operación realizada va a ser revertida. Todo o nada.
➡️ Imagina que estás reservando un vuelo. Esta operación consisten en dos pasos:
Crear la reserva del vuelo.
Restar -1 asiento al número de asientos disponibles.
BEGIN;
INSERT INTO bookings (flight_id, passenger_id, seat) VALUES ('IB123', 42, '12A');
UPDATE flights SET available_seats = available_seats - 1 WHERE flight_id = 'IB123';
COMMIT;
La atomicidad asegura que o se ejecutan ambas operaciones o que ninguna lo hace. Si el sistema se cae justo después de crear la reserva pero antes de reducir el número de asientos disponibles, la base de datos revertirá la transacción entera.
🔵Consistencia (consistency)
Las transacciones transforman el conjunto de datos de un estado consistente a otro, garantizando que cuando se complete, se cumplan todas las restricciones definidas en el sistema.
➡️ Por ejemplo, digamos que tenemos una regla en nuestra base de datos para que el número de asientos disponibles en un vuelo nunca sea negativo:
CREATE TABLE flights (
flight_id TEXT PRIMARY KEY,
available_seats INT CHECK (available_seats >= 0)
);
Si la transacción hiciese que el número de asientos disponibles fuese negativo, la base de datos rechazaría la transacción completa.
🟢Aislamiento (isolation)
Las transacciones pueden ejecutarse en paralelo sin afectar la una a la otra. Es decir, una transacción no puede acceder a los cambios intermedios de otra mientras se ejecuta.
La mayoría de bases de datos permiten 4 niveles diferentes de aislamiento:
READ UNCOMMITED: pueden ver cambios de otras transacciones que aún no han hecho commit (se usa raras veces).
READ COMMITED: solo pueden ver cambios de transacciones commiteadas (por defecto en PostgreSQL).
REPEATABLE READ: si lees el mismo dato varias veces, aunque otra transacción haga un cambio y commit, seguirá leyendo el mismo dato (por defecto en MySQL).
SERIALIZABLE: provee del aislamiento más fuerte, las transacciones se ejecutan una tras otra en orden.
➡️ En nuestro ejemplo de reservas de vuelos, supongamos que solo queda un asiento disponible para el vuelo IB123
.
flight_id | available_seats |
IB123 | 1 |
Con un nivel de aislamiento READ COMMITTED, podría ocurrir que dos transacciones intenten reservar ese asiento al mismo tiempo. Ambas leen que el asiento está disponible. La primera transacción termina primero y hace commit, reduciendo el número de asientos disponibles a 0.
Al hacer commit, la segunda transacción también disminuye el contador de asientos a 0, provocando un overbooking: el mismo asiento se ha vendido dos veces.
Si en su lugar usamos un aislamiento SERIALIZABLE, la base de datos evita automáticamente este conflicto: aborta una de las transacciones que interfiere con la otra. La transacción abortada puede ser reintentada de manera segura, asegurando que nunca se reserve más de un asiento de los disponibles.
BEGIN;
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
-- o REPEATABLE READ
-- o SERIALIZABLE
COMMIT;
Esto no significa que sea la mejor solución para este caso, ya que habilitar el modo SERIALIZABLE puede afectar el rendimiento. Sin embargo, en este caso sí garantizaría que la operación funcione de forma segura.
🟠Durabilidad (durability)
Cuando una transacción es completada, los datos deben persistir en el sistema aunque haya un fallo en el servidor. Los datos nunca pueden perderse.
➡️ En nuestro sistema de reserva de vuelos, si la transacción se completa, el asiento queda reservado incluso si el servidor se apaga después. La confirmación del COMMIT
asegura que la reserva esté escrita en disco.
📢Por qué ACID sigue importando
Al elegir qué base de datos utilizar para tu sistema, es importante valorar si priorizamos más la disponibilidad o la consistencia. Como vimos en ¿Qué es el teorema CAP?, en sistemas distribuidos normalmente hay que priorizar una propiedad sobre la otra, al menos en cierta parte del sistema. Por ello, elegir una base de datos que cumpla con las propiedades ACID es una excelente opción cuando la consistencia es vital (tal como se define en el teorema CAP).
Considera los siguientes escenarios:
Transacciones financieras: aquí es imprescindible contar con ACID para evitar perder transacciones de dinero o realizar dos veces el mismo pago.
Los likes en redes sociales: seguramente una eventual consistency será suficiente, ya que por perder un like no va a pasar nada.
Autenticación de usuarios: probablemente requieras ACID para prevenir problemas de seguridad.
Análisis de datos: aquí quizás quieras priorizar el performance antes que una fuerte consistencia.
Así que la respuesta es: sí, ACID sigue importando. Cuando te encuentres en un caso donde priorices la consistencia de los datos, piensa en ACID como una herramienta que te va a ayudar a conseguir esa fuerte consistencia.
📅Bases de datos que soportan ACID hoy en día
Tradicionalmente, soportar las propiedades ACID era una característica de muchas bases de datos relacionales como MySQL o PostgreSQL. Sin embargo, en los últimos años, muchas bases de datos NoSQL también han comenzado a dar soporte parcial o completo a transacciones ACID. Entre las más famosas:
Cassandra: ofrece transacciones atómicas, aisladas y duraderas con una consistencia a elegir entre eventual o fuerte según como se quieran las transacciones.
DynamoDB: ofrece transacciones ACID desde 2018.
CockroachDB: tiene soporte complete para transacciones ACID distribuidas.
MongoDB: ofrece transacciones multi-document.
Así que no pienses que si quieres transacciones que cumplan con propiedades ACID te tengas que ir a una base de datos relacional, porque muchas NoSQL también lo soportan.
Fuentes:
Subscribe to my newsletter
Read articles from Juanjo Requena directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Juanjo Requena
Juanjo Requena
👋 Hey there! I'm Juanjo, a Backend Software Engineer with a focus on API development. My colleagues know me as someone committed to quality and attention to detail, my friends know me as a funny guy who knows good places to eat food. This blog tries to blend both sides of me.