Watch at EaseHistorias. Respuestas. Perspectiva.

Tecnología · GUÍA PRÁCTICA

¿PostgreSQL SQLSTATE 40001? Reintente toda la transacción, no la sentencia fallida

Registre SQLSTATE, aislamiento y límite del fallo; revierta y repita cada lectura y decisión con un presupuesto acotado, dejando los efectos irreversibles después del commit.

Ilustración técnica original: Ilustración original: tras 40001 se repite desde BEGIN y los efectos externos quedan después del commit.
Ilustración técnica original: Ilustración original: tras 40001 se repite desde BEGIN y los efectos externos quedan después del commit. Watch at Ease

SQLSTATE 40001 es serialization_failure en PostgreSQL. Puede aparecer con Repeatable Read o Serializable y puede llegar durante COMMIT. La base rechazó el intento completo; repetir solo la última sentencia reutiliza decisiones derivadas de una instantánea que ya no es válida.

Un controlador seguro envuelve el callback completo y COMMIT: confirma 40001, revierte, espera con backoff y jitter acotados, inicia otra transacción y repite lecturas, decisiones y escrituras. PostgreSQL no puede reconstruir automáticamente la lógica que eligió SQL y valores.

Reintentar no debe ocultar contención. Fije un límite de intentos o tiempo, mida y exponga el agotamiento. Correo, cobros, publicación y otros efectos irreversibles deben ir después del commit; un outbox transaccional o clave de idempotencia conecta el estado confirmado con la entrega.

Registre el límite del fallo antes de reintentar

Registre SQLSTATE, aislamiento, intento, edad de la transacción y si falló una sentencia o COMMIT. Controle por código, no por texto traducido.

Un fallo en COMMIT es posible: el servidor puede necesitar el conjunto completo de lecturas y escrituras para decidir el orden seguro.

Repita desde BEGIN con lecturas nuevas

Tras rollback, vuelva a la primera lectura. Recalcule existencia, inventario, precios, autorización y valores derivados. Repetir solo UPDATE o un savepoint conserva supuestos inválidos.

Haga que una invocación del callback sea un intento y capture tanto callback como COMMIT.

Acote los intentos y muestre la contención

Use pocos intentos o tiempo total, backoff y jitter. Reinicie el estado en cada intento y no reutilice una transacción abortada.

Mida por operación. El agotamiento exige revisar transacciones largas, claves calientes, índices, pool y necesidad de aislamiento; no reduzca aislamiento como parche.

Deje efectos fuera del límite seguro de commit

El callback puede ejecutarse varias veces. No envíe correo, cobre, publique ni llame API no idempotentes antes del commit.

Escriba un outbox en la misma transacción y publique después. Use una clave de idempotencia derivada de la solicitud estable del negocio.

Separe los SQLSTATE vecinos

40P01 es deadlock: puede reintentarse pero requiere revisar el orden de bloqueos. 23505 necesita prueba de la aplicación antes de automatizar.

40003 indica resultado desconocido y exige reconciliar antes de repetir. Reintentar toda la clase 40 puede duplicar trabajo.

Ilustración técnica original: Tabla original: rutas distintas para 40001, 40P01, 23505 y 40003.
Ilustración técnica original: Tabla original: rutas distintas para 40001, 40P01, 23505 y 40003. Watch at Ease