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