Watch at EaseHistorias. Respuestas. Perspectiva.

Tecnología · GUÍA PRÁCTICA

¿PostgreSQL dice que la transacción actual está abortada? Encuentra el primer error antes de reintentar

Trata SQLSTATE 25P02 como la consecuencia de un fallo anterior: conserva el primer SQLSTATE, identifica la conexión y el dueño de la transacción, y luego elige un rollback total o un savepoint creado antes del trabajo riesgoso.

Diagrama original de una operación fallida que deja bloqueadas las órdenes posteriores.
Ilustración original: los 25P02 posteriores son consecuencias; conserva el primer fallo. Watch at Ease

El mensaje “current transaction is aborted” de PostgreSQL suele ser la consecuencia de una sentencia anterior que falló en la misma transacción. Repetir la última orden no repara el estado y puede ocultar la causa original.

La secuencia segura es guardar el primer error, vincularlo con una conexión y un dueño de transacción concretos, elegir una recuperación válida y comprobar la conexión antes de reintentar o devolverla al pool.

Congela el primer fallo antes de recuperar

25P02 indica que una sentencia anterior falló y PostgreSQL ignorará las órdenes posteriores hasta recuperar la transacción. Guarda el primer error del servidor, SQLSTATE, una huella segura de la sentencia, tipos de parámetros, hora y pila antes del rollback.

Si la primera línea visible ya es 25P02, amplía la ventana de logs y busca sentencias generadas por el cliente, triggers, restricciones y excepciones anteriores en la misma conexión.

Demuestra la conexión y el límite de la transacción

Registra instancia, pool, identificador de conexión, usuario, PID del backend, autocommit y hora de inicio. Una petición puede usar varias conexiones y una conexión del pool puede servir varias peticiones.

Identifica quién abrió la transacción: BEGIN, ORM, migración, cuaderno, cliente o el comportamiento implícito del driver. Psycopg inicia por defecto una transacción incluso con SELECT si autocommit no está activado.

Haz rollback total cuando no exista un savepoint seguro

Si se puede abandonar la unidad, llama al rollback del driver o framework y confirma que la conexión dejó el estado fallido antes de reintentar. Devolver una conexión abortada al pool propaga el síntoma.

El rollback total elimina todos los cambios no confirmados. Registra el trabajo que se perderá y el dueño de la transacción; no uses COMMIT para intentar ocultar el error.

Usa solo savepoints creados antes del trabajo riesgoso

Solo un savepoint anterior al fallo puede conservar el trabajo previo. Ejecuta ROLLBACK TO SAVEPOINT para recuperar el bloque y después decide si continúas o lo liberas. Crearlo después de ver 25P02 es demasiado tarde.

PostgreSQL no permite RELEASE SAVEPOINT mientras la transacción sigue abortada. Si el framework creó el savepoint, usa su API para mantener sincronizados cliente y servidor.

Audita sentencias ocultas de pools, ORM y clientes

Comprueba si health checks, conteos, consultas de metadatos, callbacks o flush automáticos se ejecutaron antes del SQL visible. El issue de DBeaver demuestra la existencia de esta familia de problemas, no que tu cliente tenga el mismo defecto.

Antes de devolver la conexión, confirma commit o rollback y el estado inactivo. En un ORM conserva la primera excepción de base de datos antes de que otra capa la envuelva.

Reintenta la unidad de trabajo, no la última sentencia

Corrige primero la causa original y reintenta desde el límite definido la unidad de negocio mínima e idempotente. Repetir solo el último INSERT o SELECT puede duplicar efectos externos.

Clasifica el reintento por el primer SQLSTATE: una restricción requiere datos corregidos, un conflicto transitorio puede admitir reintentos limitados y un permiso requiere configuración.

Verifica una conexión limpia antes de devolverla

Ejecuta una comprobación inocua por la misma ruta del framework y confirma en el estado o logs del pool que la siguiente transacción empieza y termina normalmente.

Cierra el incidente con el primer SQLSTATE, dueño, conexión, rama de recuperación, trabajo perdido, decisión de reintento y prevención.

Diagrama original que compara rollback total con retorno a un savepoint anterior.
Ilustración original: usa el savepoint solo si existía antes del trabajo riesgoso y el dueño de la transacción lo espera. Watch at Ease