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

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.

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 encoding!

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.

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 / database / # 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).

En Frask solo tienes que escribir:

 curs = conn.cursor() curs.execute("ROLLBACK") conn.commit() 

La documentación de PS se encuentra aquí https://www.postgresql.org/docs/9.4/static/sql-rollback.html

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

Encontré un comportamiento similar mientras ejecutaba una transacción que no funcionaba correctamente 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;

Tengo el problema de silimar. La solución fue migrar db ( manage.py syncdb o manage.py schemamigration --auto

si usas el sur).

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);") 

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 

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.

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.

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 

En el shell Flask, todo lo que tenía que hacer era un session.rollback() para superar esto.

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