with postgres engine conectar con backends python django postgresql psycopg2 psycopg

python - postgres - DatabaseError: la transacción actual se cancela, los comandos se ignoran hasta el final del bloque de transacción



psycopg2 python 3 (16)

Creo que el patrón que menciona clcc es más probable que sea la causa habitual de este problema cuando se usa PostgreSQL.

Sin embargo, siento que existen usos válidos para el patrón y no creo que este problema deba ser una razón para evitarlo siempre. Por ejemplo:

try: profile = user.get_profile() except ObjectDoesNotExist: profile = make_default_profile_for_user(user) do_something_with_profile(profile)

Si se siente bien con este patrón, pero desea evitar el código explícito de manejo de transacciones en todo el lugar, entonces debería considerar activar el modo de confirmación automática (PostgreSQL 8.2+): https://docs.djangoproject.com/en/dev/ref/databases/#autocommit-mode

DATABASES[''default''] = { #.. you usual options... ''OPTIONS'': { ''autocommit'': True, } }

No estoy seguro de si hay consideraciones de rendimiento importantes (o de cualquier otro tipo).

Recibí muchos errores con el mensaje:

"DatabaseError: current transaction is aborted, commands ignored until end of transaction block"

después de cambiar de python-psycopg a python-psycopg2 como motor de base de datos del proyecto Django.

El código sigue siendo el mismo, simplemente no sé de dónde provienen esos errores.


Creo que la respuesta de @ AnujGupta es correcta. Sin embargo, la reversión puede generar una excepción que debe capturar y manejar:

from django.db import transaction, DatabaseError try: a.save() except DatabaseError: try: transaction.rollback() except transaction.TransactionManagementError: # Log or handle otherwise

Si descubre que está reescribiendo este código en varias ubicaciones de save() , puede extraer el método:

import traceback def try_rolling_back(): try: transaction.rollback() log.warning(''rolled back'') # example handling except transaction.TransactionManagementError: log.exception(traceback.format_exc()) # example handling

Finalmente, puede pretenderlo utilizando un decorador que protege los métodos que usan save() :

from functools import wraps def try_rolling_back_on_exception(fn): @wraps(fn) def wrapped(*args, **kwargs): try: return fn(*args, **kwargs) except: traceback.print_exc() try_rolling_back() return wrapped @try_rolling_back_on_exception def some_saving_method(): # ... model.save() # ...

Incluso si implementa el decorador anterior, aún es conveniente mantener try_rolling_back() como un método extraído en caso de que necesite usarlo manualmente para casos donde se requiera un manejo específico, y el manejo genérico del decorador no sea suficiente.



En el shell Flask, todo lo que necesitaba hacer era una session.rollback() para superar esto.


En mi experiencia, estos errores ocurren de esta manera:

try: code_that_executes_bad_query() # transaction on DB is now bad except: pass # transaction on db is still bad code_that_executes_working_query() # raises transaction error

No hay nada malo con la segunda consulta, pero como se detectó el error real, la segunda consulta es la que genera el error (mucho menos informativo).

edición: esto solo sucede si la cláusula de except detecta IntegrityError (o cualquier otra excepción de base de datos de bajo nivel). Si DoesNotExist algo como DoesNotExist este error no aparecerá, porque DoesNotExist no daña la transacción.

La lección aquí es no intente / excepto / pase.


En respuesta a @priestc y @Sebastian, ¿qué pasa si haces algo como esto?

try: conn.commit() except: pass cursor.execute( sql ) try: return cursor.fetchall() except: conn.commit() return None

Acabo de probar este código y parece funcionar, fallando en silencio sin tener que preocuparme por los posibles errores y trabajando cuando la consulta es buena.


Encontré un comportamiento similar mientras ejecutaba una transacción defectuosa en el terminal de postgres . Nada pasó después de esto, ya que la database está en un estado de error . Sin embargo, solo como una solución rápida, si puede permitirse evitar la rollback transaction . A continuación hice el truco para mí:

COMMIT;


Este es un comportamiento muy extraño para mí. Me sorprende que nadie haya pensado en los puntos de salvamento. En mi código, la consulta era el comportamiento esperado:

from django.db import transaction @transaction.commit_on_success def update(): skipped = 0 for old_model in OldModel.objects.all(): try: Model.objects.create( group_id=old_model.group_uuid, file_id=old_model.file_uuid, ) except IntegrityError: skipped += 1 return skipped

He cambiado el código de esta manera para usar los puntos guardados:

from django.db import transaction @transaction.commit_on_success def update(): skipped = 0 sid = transaction.savepoint() for old_model in OldModel.objects.all(): try: Model.objects.create( group_id=old_model.group_uuid, file_id=old_model.file_uuid, ) except IntegrityError: skipped += 1 transaction.savepoint_rollback(sid) else: transaction.savepoint_commit(sid) return skipped


Esto es lo que hace postgres cuando una consulta produce un error e intenta ejecutar otra consulta sin revertir primero la transacción. (Podría pensar que es una característica de seguridad para evitar que corrompa sus datos).

Para solucionar este problema, querrá averiguar en qué parte del código se está ejecutando la consulta incorrecta. Puede ser útil usar las opciones log_statement y log_min_error_statement en su servidor postgresql.


Para deshacerse del error, deshaga la última transacción (errónea) una vez que haya corregido su código:

from django.db import transaction transaction.rollback()

Puede usar try-except para evitar que ocurra el error:

from django.db import transaction, DatabaseError try: a.save() except DatabaseError: transaction.rollback()

Consulte: documentación de Django.


Por lo tanto, me encontré con este mismo problema. El problema que estaba teniendo aquí era que mi base de datos no estaba sincronizada correctamente. Los problemas simples siempre parecen causar la mayor angustia ...

Para sincronizar su django db, desde dentro del directorio de su aplicación, dentro de la terminal, escriba:

$ python manage.py syncdb

Edición: tenga en cuenta que si está utilizando django-south, ejecutar el comando ''$ python manage.py migrate'' también puede resolver este problema.

¡Feliz codificación!


Si obtiene esto mientras está en el shell interactivo y necesita una solución rápida, haga lo siguiente:

from django.db import connection connection._rollback()

visto originalmente en esta respuesta


También tuve este error, pero estaba ocultando otro mensaje de error más relevante cuando el código intentaba almacenar una cadena de 125 caracteres en una columna de 100 caracteres:

DatabaseError: value too long for type character varying(100)

Tuve que depurar a través del código para que aparezca el mensaje anterior, de lo contrario se muestra

DatabaseError: current transaction is aborted


Tengo el problema silimar. La solución fue migrar db ( manage.py syncdb o manage.py schemamigration --auto <table name> si usas el sur).


puede deshabilitar la transacción a través de "set_isolation_level (0)"


solo usa revertir

Código de ejemplo

try: cur.execute("CREATE TABLE IF NOT EXISTS test2 (id serial, qa text);") except: cur.execute("rollback") cur.execute("CREATE TABLE IF NOT EXISTS test2 (id serial, qa text);")