Джанго "Тупик найден" с транзакцией. - PullRequest
0 голосов
/ 07 мая 2018

У меня есть функция, которая обновляет модель или создает новую запись, если она еще не существует:

try:            
  obj=model.objects.get(id=id)
  setattr(obj, 'completed', True)
  obj.save()
except:
  model.objects.create(id=x, user=y, completed=True)

В конкретном случае эта функция вызывается вдвое быстрее, так что она создала две записи в базе данных, поэтому я включил уникальное ограничение, чтобы гарантировать, что это никогда не произойдет.

Но потом я начал получать эту ошибку:

Duplicate entry '1-13' for key 'x_y_z_uniq'

Итак, я попытался использовать блокировку как:

with transaction.atomic():
  try:            
    obj=model.objects.select_for_update().get(id=id)
    setattr(obj, 'completed', True)
    obj.save()
  except:
    model.objects.create(id=x, user=y, completed=True)

Но сейчас поднимается эта ошибка:

(Deadlock found when trying to get lock; try restarting transaction)

Я хотел, чтобы первый вызов функции создал новую запись, а второй обновил бы эту запись, но второй вызов просто завершился неудачей из-за тупика, как я могу сделать так, чтобы второй вызов ожидал для первого, чтобы закончить?

1 Ответ

0 голосов
/ 08 мая 2018

Мне кажется, вы можете использовать здесь простой .update() метод:
obj=model.objects.filter(id=id).update(completed=True)

Более того, вы можете изменить свой код на this :

obj, created = model.objects.update_or_create(
    id=id,
    defaults={'id': x, 'user': y, 'completed': True}
)
...