Это может быть следствием той же проблемы, что и здесь:
Почему этот цикл не отображает обновленный счетчик объектов каждые пять секунд?
В основном get_or_create может потерпеть неудачу - если вы посмотрите на его источник, то увидите, что это: get, if-problem: save + some_trickery, if-still проблема: получить снова, если проблема все еще: сдаться и поднять.
Это означает, что если два одновременно работающих потока (или процесса) работают create_or_update_myobj
, и оба пытаются получить один или один и тот же объект, то:
- Первый поток пытается получить его - но он еще не существует,
- Итак, поток пытается создать его, но до создания объекта ...
- ... второй поток пытается получить его - и это, очевидно, не удается
- теперь, поскольку по умолчанию 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-транзакции, и-django.html
http://www.no -ack.org / 2011/05 / разбитая транзакция управление в-mysql.html