Interbloqueos: detección y prevención
Comprenda cómo se producen los interbloqueos, cómo los detecta Postgres y diseñe reglas de ordenación de bloqueos que los eviten.
Interbloqueos: detección y prevención es una lección gratuita de SQL Academy en CoddyKit. Esta es la lección 3 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de SQL Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de SQL Academy incluye 4 lecciones en total.
¿Qué es un interbloqueo?
Dos transacciones tienen cada una un bloqueo que la otra necesita; ninguna puede continuar. La base de datos detecta el ciclo y aborta una de las transacciones.
Un interbloqueo clásico
La transacción A bloquea la fila 1 y la transacción B bloquea la fila 2. A solicita la fila 2 y B solicita la fila 1. Se quedan bloqueadas.
-- Tx A:
BEGIN;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
UPDATE accounts SET balance = balance + 100 WHERE id = 2;
-- waiting for B...
-- Tx B:
BEGIN;
UPDATE accounts SET balance = balance - 50 WHERE id = 2;
UPDATE accounts SET balance = balance + 50 WHERE id = 1;
-- waiting for A...
-- ERROR: deadlock detectedPostgreSQL detecta los interbloqueos
Cada deadlock_timeout (1 segundo de forma predeterminada), PostgreSQL comprueba si hay ciclos de bloqueos. Si encuentra uno, aborta una transacción con el código de error 40P01.
ERROR: deadlock detected
DETAIL: Process 1234 waits for ShareLock on transaction 5678 ...Regla de orden de los bloqueos
La solución: adquiera siempre los bloqueos en el mismo orden en todas las rutas del código.
-- Always update the lower id first:
UPDATE accounts SET balance = balance - 100 WHERE id = LEAST(:from, :to);
UPDATE accounts SET balance = balance + 100 WHERE id = GREATEST(:from, :to);Interbloqueos en filas muy solicitadas
Las actualizaciones rápidas de las mismas filas muy solicitadas suelen provocar esperas por bloqueos, no interbloqueos. Utilice colas, particione la fila muy solicitada o serialice las actualizaciones en el código de la aplicación.
FOR UPDATE bloquea las filas leídas
Adquiera bloqueos de escritura al leer para evitar sorpresas más adelante:
BEGIN;
SELECT * FROM accounts WHERE id IN (1, 2) ORDER BY id FOR UPDATE;
-- both rows locked in id order
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
UPDATE accounts SET balance = balance + 100 WHERE id = 2;
COMMIT;Omitir filas bloqueadas
Para tablas de colas, utilice el patrón «tomar cualquier fila disponible»:
SELECT * FROM jobs
WHERE status = 'pending'
ORDER BY created_at
LIMIT 1
FOR UPDATE SKIP LOCKED;
-- skips rows other workers have lockedNOWAIT
Falle inmediatamente en lugar de esperar:
SELECT * FROM accounts WHERE id = 1 FOR UPDATE NOWAIT;
-- ERROR: could not obtain lock on row in relation "accounts"Diagnóstico de interbloqueos
Aumente log_lock_waits y capture el contexto del interbloqueo en el registro. La entrada del registro muestra ambas transacciones y sus consultas.
Bucle de reintento en la aplicación
Los interbloqueos se pueden resolver: vuelva a intentar la transacción abortada:
for (let attempt = 0; attempt < 3; attempt++) {
try {
await runTransaction();
break;
} catch (e) {
if (e.code === '40P01') continue; // deadlock
throw e;
}
}Reducir el alcance de los bloqueos
Acorte las transacciones: cada fila afectada permanece bloqueada hasta COMMIT. No realice llamadas HTTP ni cálculos largos dentro de una transacción.
Indexar las claves foráneas para evitar la escalada de bloqueos
Al eliminar un elemento principal, se comprueba cada fila secundaria. Sin un índice en la FK, eso implica un escaneo completo de la tabla Y bloqueos de filas. Indexe cada columna FK.
Resumen
Los interbloqueos ocurren; diseñe el sistema para minimizarlos.
- Adquiera los bloqueos en un orden coherente
- Utilice FOR UPDATE pronto para declarar la intención
- Utilice SKIP LOCKED para las colas
- Reintente cuando se produzcan errores de interbloqueo (40P01)
- Mantenga cortas las transacciones
Comprobación rápida
¿Cuál es el principio de diseño más fiable para evitar interbloqueos?
Preguntas frecuentes
¿La lección «Interbloqueos: detección y prevención» es gratis?
Sí — el texto completo de «Interbloqueos: detección y prevención» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de SQL Academy, actualiza a CoddyKit PRO. El curso de SQL Academy incluye 4 lecciones en total.
¿Qué aprenderé en «Interbloqueos: detección y prevención»?
Comprenda cómo se producen los interbloqueos, cómo los detecta Postgres y diseñe reglas de ordenación de bloqueos que los eviten. Practicas SQL Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.
¿Necesito experiencia previa para empezar SQL Academy?
No se requiere experiencia previa. SQL Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 3 de 4.
¿Cuánto tiempo toma la lección «Interbloqueos: detección y prevención»?
La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.
¿Puedo escribir y ejecutar código en esta lección de SQL Academy?
Sí. Cada lección de SQL Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.
Todas las lecciones de este curso
- Propiedades ACID y anomalías
- Niveles de aislamiento: READ COMMITTED, REPEATABLE READ, SERIALIZABLE
- Interbloqueos: detección y prevención
- Bloqueo optimista frente a pesimista