4 votes

django/innodb -- problème avec les anciennes sessions et transactions

Nous venons de changer notre base de données MySQL de MyIsam à Innodb, et nous constatons un problème étrange dans Django. Chaque fois que nous effectuons une transaction dans la base de données, les sessions existantes ne la récupèrent pas... jamais. Nous pouvons voir le nouvel enregistrement dans la base de données à partir d'un terminal mysql, mais les sessions django existantes (c'est-à-dire un shell déjà ouvert), n'enregistrent pas le changement. Par exemple :

Coquille 1 :

>>> my_obj = MyObj.objects.create(foo="bar")
>>> my_obj.pk
1

Coquille 2 (était ouverte avant ce qui précède)

>>> my_obj = MyObj.objects.filter(pk=1)
[]

Shell 3 (MySQL) :

mysql> select id from myapp_my_obj where id = 1;
id
1

Quelqu'un sait-il pourquoi cela peut se produire ?

EDIT : Pour clarifier, Shell 2 a été ouvert avant Shell 1, puis je fais la création Shell 1, puis j'essaie de visualiser l'objet que j'ai créé dans Shell 2.

EDIT2 : Le problème est que j'ai une tâche celery qui reçoit la clé primaire de l'objet qui est créé. Quand j'utilisais MyISAM, il la trouvait à chaque fois, et maintenant il lance ObjectDoesNotExist même si je peux voir que l'objet est créé dans la base de données.

7voto

Paul McMillan Points 11723

Votre create() commet la transaction pour le shell actuel, mais ne fait rien à la transaction dans le second shell.

https://docs.djangoproject.com/en/dev/topics/db/transactions/

Votre deuxième fil ne peut pas voir ce qui est fait dans le premier parce qu'il est dans une transaction qui lui est propre. Les transactions isolent la base de données de sorte que lorsqu'une transaction est validée, tout se passe en un seul point dans le temps, y compris les instructions select. C'est le A en ACID . Essayez d'exécuter

from django.db import transaction; transaction.commit()

dans la deuxième coquille. Cela devrait valider la transaction actuelle et en démarrer une nouvelle. Vous pouvez également utiliser transaction.rollback() pour obtenir la même chose si vous n'avez rien modifié dans la base de données dans le shell actuel.

Editer Editer :

Il se peut que vous deviez saisir votre connexion de base de données spécifique pour que cela fonctionne. Essayez ceci :

import django.db
django.db.connection._commit() 

Plus d'informations sur ce problème ici :

http://groups.google.com/group/django-users/msg/55fa3724d2754013

La partie pertinente est :

If you want script1.py (using an InnoDB table) to see committed updates from 
other transactions you can change the transaction isolation level like so: 

from django.db import connection 
connection.cursor().execute('set transaction isolation level read 
committed') 

Alternatively you can enable the database's version of auto-commit, which 
"commits" queries as well as updates, so that each new query by script1 will 
be in its own transaction: 

connection.cursor().execute('set autocommit=1') 
Either one allows script1 to see script2's updates. 

En résumé, vous devez définir l'isolation des transactions InnoDB comme suit READ-COMMITTED .

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