294 votes

DatabaseError : la transaction en cours est interrompue, les commandes sont ignorées jusqu'à la fin du bloc de transaction ?

J'ai eu beaucoup d'erreurs avec le message :

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

après avoir changé de python-psycopg à python-psycopg2 comme moteur de base de données du projet Django.

Le code reste le même, mais je ne sais pas d'où viennent ces erreurs.

4 votes

Je suis curieux de savoir quelle a été votre solution finale à ce problème ? J'ai le même problème, mais comme mon hébergeur n'enregistre pas les erreurs de requête, il m'a été impossible jusqu'à présent de comprendre ce qui ne va pas.

2 votes

J'ai finalement trouvé un problème lié à l'utilisation d'une table de base de données comme support de cache. Bogue Django : code.djangoproject.com/ticket/11569 Discussion StackOverflow : stackoverflow.com/questions/1189541/

11 votes

FYI Si vous utilisez juste psycopg2 sans django, conn.rollback() (où conn est votre objet de connexion) supprimera l'erreur et vous pourrez exécuter d'autres requêtes.

204voto

ʇsәɹoɈ Points 8284

Voici ce que fait postgres lorsqu'une requête produit une erreur et que vous essayez d'exécuter une autre requête sans annuler la transaction au préalable. (Vous pouvez considérer cela comme une fonction de sécurité, pour vous empêcher de corrompre vos données).

Pour résoudre ce problème, vous devez déterminer à quel endroit du code la mauvaise requête est exécutée. Il peut être utile d'utiliser la fonction déclaration de journal y enregistrement_minimum_de_l'erreur dans votre serveur postgresql.

0 votes

Le problème est que lorsque j'utilisais python-psycopg, aucune erreur de ce type n'apparaissait. psycopg2 met-il en œuvre un mécanisme différent pour communiquer avec postgres ?

5 votes

La méthode de communication avec le serveur n'a probablement pas d'importance, mais il est possible que la version que vous avez utilisée auparavant ait adopté le mode autocommit par défaut alors que la nouvelle version ne l'a pas fait. L'erreur aurait pu se produire, mais vous auriez pu plus facilement la manquer. Il est également possible que la conversion des types de données ou quelque chose d'autre ait changé depuis l'ancienne version. Quoi qu'il en soit, la meilleure solution consiste à retrouver la requête erronée afin de déterminer ce qui ne va pas.

145voto

Anuj Gupta Points 2962

Pour se débarrasser de l'erreur, annuler la dernière transaction (erronée) après avoir corrigé votre code :

from django.db import transaction
transaction.rollback()

Vous pouvez utiliser try-except pour éviter que l'erreur ne se produise :

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

Référer : Documentation sur Django

3 votes

Cela résout le problème principal et vous permet de récupérer après une déclaration qui a causé l'interruption de la transaction.

0 votes

Ceci, combiné avec essayer / sauf.

3 votes

Pourquoi utiliser IntegrityError et non la classe de base DatabaseError ?

51voto

Michael Merchant Points 806

Donc, j'ai rencontré le même problème. Le problème que j'avais ici était que ma base de données n'était pas correctement synchronisée. Les problèmes simples semblent toujours causer le plus d'angoisse...

Pour synchroniser votre django db, depuis le répertoire de votre application, dans le terminal, tapez :

$ python manage.py syncdb

Modification : si vous utilisez django-sud, l'exécution de la commande '$ python manage.py migrate' peut également résoudre ce problème.

Bon codage !

3 votes

Upvoted pour avoir énoncé l'évidence. Je ne lui donnerais pas plus d'un vote positif parce que ce n'est probablement pas la réponse recherchée.

5 votes

Je l'ai réparé d'une manière similaire en python manage.py migrate <app> ... pour toutes mes applications.

3 votes

@Clayton - vous ne le dites pas, mais je suppose que vous utilisez django-south - le migrate n'est pas intégrée à Django.

38voto

priestc Points 5002

D'après mon expérience, ces erreurs se produisent de cette façon :

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

Il n'y a rien d'anormal dans la deuxième requête, mais comme la véritable erreur a été détectée, c'est la deuxième requête qui soulève l'erreur (beaucoup moins informative).

edit : cela ne se produit que si le except clause attrape IntegrityError (ou toute autre exception de base de données de bas niveau), si vous attrapez quelque chose comme DoesNotExist cette erreur n'apparaîtra pas, car DoesNotExist ne corrompt pas la transaction.

La leçon à retenir est qu'il ne faut pas faire de try/except/pass.

16voto

Sebastian Points 324

Je pense que le modèle mentionné par priestc est plus susceptible d'être la cause habituelle de ce problème lors de l'utilisation de PostgreSQL.

Cependant, je pense qu'il existe des utilisations valables de ce modèle et je ne pense pas que ce problème doive être une raison pour l'éviter systématiquement. Par exemple :

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

do_something_with_profile(profile)

Si vous vous sentez à l'aise avec ce modèle, mais que vous voulez éviter d'avoir du code explicite de gestion des transactions partout, vous pouvez envisager d'activer le mode autocommit (PostgreSQL 8.2+) : https://docs.djangoproject.com/en/dev/ref/databases/#autocommit-mode

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

Je ne suis pas sûr qu'il y ait d'importantes considérations de performance (ou de tout autre type).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X