django/innodb -- 旧会话和事务的问题

发布于 2024-11-10 16:59:45 字数 724 浏览 3 评论 0原文

我们刚刚将 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 中创建的对象。

编辑2:大局是我有一个 celery 任务正在执行传递来自创建的对象的主键。当我使用MyISAM时,它每次都找到它,现在它抛出ObjectDoesNotExist,即使我可以看到该对象是在数据库中创建的。

We just switched our MySQL database from MyIsam to Innodb, and we are seeing an odd issue arise in Django. Whenever we make a database transaction, the existing sessions do not pick it up...ever. We can see the new record in the database from a mysql terminal, but the existing django sessions (ie a shell that was already open), would not register the change. For example:

Shell 1:

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

Shell 2 (was open before the above)

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

Shell 3 (MySQL):

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

Does anyone know why this might be happening?

EDIT: To clarify, Shell 2 was opened before Shell 1, then I make the create Shell 1, then I try to view the object that I created in Shell 2.

EDIT2: The big picture is that I have a celery task that is being passed the primary key from the object that is created. When I was using MyISAM, it found it every time, and now it throws ObjectDoesNotExist, even though I can see that the object is created in the database.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

痴梦一场 2024-11-17 16:59:45

您的 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. 

因此,简单地说,您需要将 InnoDB 事务隔离设置为READ-COMMITTED

Your create() command commits the transaction for the current shell, but doesn't do anything to the transaction in the second shell.

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

Your second thread that can't see what's done in the first because it is in a transaction of its own. Transactions isolate the database so that when a transaction is committed, everything happens at a single point in time, including select statements. This is the A in ACID. Try running

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

in the second shell. That should commit the current transaction and start a new one. You can also use transaction.rollback() to acheive the same thing if you haven't modified anything in the db in the current shell.

Edit Edit:

You may need to grab your specific db connection to make this work. Try this:

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

More information about this problem here:

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

The relevant bit is:

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. 

So, the tl;dr is that you need to set your InnoDB transaction isolation to READ-COMMITTED.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文