我们刚刚将MySQL数据库从MyIsam切换到Innodb,我们看到Django出现了一个奇怪的问题。每当我们进行数据库事务时,现有的会话都不会捡起它......我们可以从mysql终端看到数据库中的新记录,但是现有的django会话(即已经打开的shell)不会注册更改。例如:
Shell 1:
>>> my_obj = MyObj.objects.create(foo="bar")
>>> my_obj.pk
1
Shell 2(在上述之前开放)
>>> my_obj = MyObj.objects.filter(pk=1)
[]
Shell 3(MySQL):
mysql> select id from myapp_my_obj where id = 1;
id
1
有谁知道为什么会这样?
编辑:为了澄清,Shell 2在Shell 1之前打开,然后我创建了Shell 1,然后我尝试查看我在Shell 2中创建的对象。
EDIT2:总体而言,我有一个芹菜任务正在从创建的对象传递主键。当我使用MyISAM时,它每次都找到它,现在它抛出ObjectDoesNotExist
,即使我可以看到该对象是在数据库中创建的。
答案 0 :(得分:7)
您的create()
命令提交当前shell的事务,但不对第二个shell中的事务做任何事情。
https://docs.djangoproject.com/en/dev/topics/db/transactions/
你的第二个线程无法看到第一个在第一个线程中完成的事情,因为它处于自己的事务中。事务隔离数据库,以便在提交事务时,所有事件都在单个时间点发生,包括select语句。这是ACID
中的A
。尝试运行
from django.db import transaction; transaction.commit()
在第二个shell中。这应该提交当前事务并开始一个新事务。如果你没有在当前shell中修改数据库中的任何内容,你也可以使用transaction.rollback()
来实现相同的功能。
修改编辑:
您可能需要获取特定的数据库连接才能使其正常工作。试试这个:
import django.db
django.db.connection._commit()
此处有关此问题的更多信息:
http://groups.google.com/group/django-users/msg/55fa3724d2754013
相关位是:
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.
因此,tl; dr是您需要将InnoDB事务隔离设置为READ-COMMITTED
。