django / innodb - проблема со старыми сессиями и транзакциями - PullRequest
4 голосов
/ 02 июня 2011

Мы только что переключили нашу базу данных MySQL с MyIsam на Innodb, и мы видим странную проблему, возникающую в Django.Всякий раз, когда мы совершаем транзакцию с базой данных, существующие сеансы не принимают ее ... никогда.Мы можем видеть новую запись в базе данных из терминала mysql, но существующие сеансы django (то есть оболочка, которая уже была открыта) не будут регистрировать изменение.Например:

Оболочка 1:

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

Оболочка 2 (ранее была открыта)

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

Оболочка 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, хотя я вижу, что объект создан в базе данных.

1 Ответ

7 голосов
/ 02 июня 2011

Ваша команда create() фиксирует транзакцию для текущей оболочки, но ничего не делает с транзакцией во второй оболочке.

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

Ваш второй поток, который можетне вижу того, что сделано в первом, потому что это происходит в собственной транзакции.Транзакции изолируют базу данных, так что когда транзакция фиксируется, все происходит в один момент времени, включая операторы select.Это A в ACID.Попробуйте запустить

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

во второй оболочке.Это должно зафиксировать текущую транзакцию и начать новую.Вы также можете использовать 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.

...