Translate

martes, 5 de mayo de 2026

SELECT FOR UPDATE en MySQL


Cuando trabajamos con sistemas concurrentes (varios usuarios o procesos accediendo a los mismos datos), uno de los problemas más comunes es la inconsistencia de datos.


Ahí es donde entra en juego una herramienta clave de MySQL:

SELECT ... FOR UPDATE


Esta sentencia que:

1. Lee filas de una tabla

2. Las bloquea para escritura

3. Hasta que la transacción finalice (COMMIT o ROLLBACK)


Esto garantiza que nadie más pueda modificar esas filas mientras vos trabajás con ellas.


Veamos un ejemplo: 


START TRANSACTION;


SELECT * 

FROM cuentas 

WHERE id = 1

FOR UPDATE;


UPDATE cuentas 

SET saldo = saldo - 100 

WHERE id = 1;


COMMIT;


En este caso:

Se bloquea la fila con id = 1

Nadie más puede modificarla hasta el COMMIT


¿Por qué es importante? Imaginá este escenario sin bloqueo:

1. Proceso A lee saldo = 100

2. Proceso B lee saldo = 100

3. Ambos descuentan 50

4. Resultado final: ❌ saldo = 50 (incorrecto)


Con FOR UPDATE:

1. Proceso A bloquea la fila

2. Proceso B espera

3. Se ejecuta A completamente

4. Luego B trabaja con datos actualizados

✔️ Resultado correcto


¿Cómo funciona internamente?

Ojo, Solo funciona con motores como InnoDB

Usa bloqueo a nivel de fila (row-level locking)

Otros SELECT FOR UPDATE:

  • Quedan esperando
  • Otros SELECT normales, pueden leer (dependiendo del isolation level)


Para no cagarla podemos usar SKIP LOCKED


SELECT * FROM tareas

WHERE estado = 'pendiente'

FOR UPDATE SKIP LOCKED;


✔️ Ignora filas bloqueadas

✔️ Ideal para workers concurrentes

Ojo, no sé si es tan aplicable, si queremos modificar todas las filas queremos modificar todas, no solo las no loqueadas.  


NOWAIT


SELECT * FROM cuentas

WHERE id = 1

FOR UPDATE NOWAIT;


❌ Falla inmediatamente si la fila está bloqueada

✔️ Útil cuando no querés esperar


Cosas a tener en cuenta:

  • Siempre usar dentro de una transacción
  • Puede generar deadlocks
  • Usar índices para evitar locks innecesarios
  • No funciona bien con tablas sin InnoDB



No hay comentarios.:

Publicar un comentario