# 💾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:

1. Crear la reserva del vuelo.
    
2. Restar -1 asiento al número de asientos disponibles.
    

```sql
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:

```sql
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.

<div data-node-type="callout">
<div data-node-type="callout-emoji">🤔</div>
<div data-node-type="callout-text">Pero ¿esta consistencia no tiene nada que ver con la del <a target="_self" rel="noopener noreferrer nofollow" href="https://blog.juanjorequena.com/cap" style="pointer-events: none">teorema CAP</a>? ¡En efecto! Es muy confuso pero se utiliza el mismo término para diferentes definiciones. En ACID, la consistencia quiere decir que la base de datos siempre seguirá ciertas reglas y restricciones. En el teorema CAP, la consistencia quiere decir que la base de datos siempre devolverá el resultado correcto, incluso si eso significa sacrificar la disponibilidad o tolerancia a particiones.</div>
</div>

### 🟢**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.

<div data-node-type="callout">
<div data-node-type="callout-emoji">⚠</div>
<div data-node-type="callout-text"><strong>¡Cuidado! </strong>Hemos dicho que las transacciones <strong>pueden </strong>ejecutarse en paralelo sin afectar la una a la otra. Eso no quiere decir que este vaya a ser el comportamiento por defecto para las transacciones en dicha base de datos. Tendrás que elegir el nivel de aislamiento que quieras para las transacciones para que esto se cumpla.</div>
</div>

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.
    

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1755728042368/5725f8d3-eb70-49e1-bb08-750e8c0c08c9.png align="center")

➡️ 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.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1755730009725/71992814-8d99-43b4-9d46-b2e7d163fa61.png align="center")

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.

```sql
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?*](https://blog.juanjorequena.com/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](https://en.wikipedia.org/wiki/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:

* [Kleppmann, Martin. *Designing Data-Intensive Applications : The Big Ideas behind Reliable, Scalable, and Maintainable Systems*. Sebastopol, CA, O’Reilly Media, 2017.](https://www.goodreads.com/book/show/23463279-designing-data-intensive-applications)
    
* [https://www.hellointerview.com/learn/system-design/deep-dives/postgres](https://www.hellointerview.com/learn/system-design/deep-dives/postgres)
