Ответ 1
Это может быть отключение той же проблемы, что и здесь:
Почему этот цикл не отображает обновленный счет объекта каждые пять секунд?
В принципе get_or_create может выйти из строя - если вы посмотрите на его источник, вы увидите, что это: get, if-problem: save + some_trickery, if-still-problem: снова получить, если-еще-проблема: сдаться и поднять.
Это означает, что если есть два одновременных потока (или процессов), выполняющих create_or_update_myobj
, оба пытающиеся get_or_create один и тот же объект, тогда:
- первый поток пытается его получить, но он еще не существует,
- поэтому поток пытается создать его, но перед созданием объекта...
- ... второй поток пытается его получить - и это, очевидно, терпит неудачу
- теперь из-за установленного по умолчанию AUTOCOMMIT = OFF для подключения базы данных MySQLdb и уровня сериализуемого REPEATABLE READ, оба потока заморозили свои представления таблицы MyObj.
- впоследствии, первый поток создает свой объект и возвращает его изящно, но...
- ... второй поток не может создать ничего, поскольку он нарушит ограничение
unique
- какой смешной, последующий
get
во втором потоке не видит объект, созданный в первом потоке, из-за замороженного представления таблицы MyObj
Итак, если вы хотите безопасно get_or_create
что-нибудь, попробуйте что-то вроде этого:
@transaction.commit_on_success
def my_get_or_create(...):
try:
obj = MyObj.objects.create(...)
except IntegrityError:
transaction.commit()
obj = MyObj.objects.get(...)
return obj
Отредактировано 27/05/2010
Существует также второе решение проблемы - используя уровень изоляции READ COMMITED, а не REPEATABLE READ. Но он менее тестировался (по крайней мере, в MySQL), поэтому с ним может быть больше ошибок/проблем, но, по крайней мере, он позволяет привязывать представления к транзакциям без фиксации в середине.
Отредактировано 22/01/2012
Вот некоторые хорошие сообщения в блоге (не мои) о MySQL и Django, связанные с этим вопросом:
http://www.no-ack.org/2010/07/mysql-transactions-and-django.html
http://www.no-ack.org/2011/05/broken-transaction-management-in-mysql.html