Облачное хранилище данных: способы избежать условий гонки

У меня есть много представлений, манипулирующих сущностями одного типа:

def view1(request, key):
    user = ndb.Key(urlsafe=key).get()
    user.x = 1
    user.put()
    ...

def view2(request, key):
    user = ndb.Key(urlsafe=key).get()
    user.y = 2
    user.put()
    ...

Очевидно, что это подвержено ошибкам из-за возможных условий гонки (последние победы):

  1. view1 считывает все данные объекта пользователя (x=None, y=None)
  2. view2 считывает все данные пользователя (x=None, y=None)
  3. вид1 user.x = 1 (x=1, y=нет)
  4. вид2 user.y = 2 (х=нет, у=2)
  5. вид1 user.put() (x=1, y=нет)
  6. вид2 user.put() (х=нет, у=2)

Каковы наилучшие способы исправить это и какое поведение считается наиболее приличным? Транзакции (один из запросов не пройдет, это нормально)?


person glmvrml    schedule 15.08.2016    source источник
comment
Да, использование транзакций — типичный метод решения таких проблем.   -  person Dan Cornilescu    schedule 15.08.2016


Ответы (1)


Оберните ваш get и поместите в транзакцию. Это гарантирует, что вы не сможете наткнуться на другое обновление.

Подробнее о транзакциях с помощью клиентской библиотеки NDB можно прочитать здесь.

В своем коде вы можете, например, просто использовать декоратор транзакций NDB:

@ndb.transactional(retries=1)
def view1(request, key):
    user = ndb.Key(urlsafe=key).get()
    user.x = 1
    user.put()
    ...

@ndb.transactional(retries=1)    
def view2(request, key):
    user = ndb.Key(urlsafe=key).get()
    user.y = 2
    user.put()
person Dan McGrath    schedule 16.08.2016