Джанго - Postgresql: транзакция и параллелизм - PullRequest
0 голосов
/ 31 января 2012

Существует много тем о параллелизме Django, но после проверки многих из них я не чувствую, что нашел свой ответ, когда дело доходит до транзакций.

Django версия 1.3.1.Postgresql версия 8.4.7.

Очень простая версия моих моделей может выглядеть так:

def Member(Model):
  money = PositiveIntegerField(default=0)
  user = OneToOneField(User, related_name='member', primary_key=True)

def Bet(Model):
  total_money = PositiveIntegerField(default=0)

У меня также есть таблица Money, которая является отношением между Участником и Bet.Это не связано напрямую с моей проблемой, но помогает мне контролировать ее, потому что на нее не могут повлиять проблемы параллелизма.то есть я просто должен посчитать свою таблицу Money, чтобы проверить правильность полей money of Member и total_money of Bet.

Хотя я не могу полагаться только на таблицу Money, и мне нужно, чтобы мои поля были правильнымипотому что я много фильтрую, используя их.

Моя первая попытка использования функции ставки была примерно такой (просто с гораздо большим количеством модификаций для намного большего количества таблиц).

def bid(user_pk, bet_pk, value):
  #create Money object
  member = User.objects.get(user_pk).member
  member.money = F('money') - value
  member.save()
  bet = Bet.objects.get(bet_pk)
  bet.total_money = F('total_money') + value
  bet.save()

ЭтоВерсия работала очень хорошо, пока я не получил мой первый сбой во время одной транзакции.Мне также пришлось скопировать и вставить все тесты из моих функций clean () в bid (), потому что я в действительности не могу использовать clean () или full_clean () в этом случае (особенно если ставка повышается после сохранения участника).

Поэтому я решил попробовать транзакцию django.

@transaction.commit_manually
def bid(user_pk, bet_pk, value):
  try:
    #create money object
    member = User.objects.get(user_pk).member
    member.money -= value
    member.clean()
    member.save()
    bet = Bet.objects.get(bet_pk)
    bet.total_money += value
    bet.clean()
    bet.save()
  except:
    transaction.rollback()
    raise
  else:
    transaction.commit()

Но без возможности использовать объект F () внутри ручной транзакции (что имеет смысл).Я столкнулся с множеством проблем с параллелизмом.

Я вижу только два решения:

  • Создайте только объекты Money во время bid () / транзакции, затем используйте асинхронныйработник (Celery?), который обновляет соответствующие поля в Member и Bet.

  • Создайте список заявок () / транзакции (Redis?) и выполните все транзакции, которые изменяют поля, связанные с деньгами.синхронный.

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

1 Ответ

1 голос
/ 31 января 2012

это будет работать? @transaction.commit_on_success def bid(user_pk, bet_pk, value): Member.objects.filter(user__pk=user_pk).update(money=F('money') - value) Bet.objects.filter(pk=bet_pk).update(total_money=F('total_money') + value)

...