Django: Как я могу защитить от параллельной модификации записей базы данных

77
задан Anton Strogonoff 6 April 2012 в 09:32
поделиться

7 ответов

На самом деле транзакции не помогают Вам очень здесь..., если Вы не хотите иметь транзакции, работающие на основе нескольких Запросов HTTP (который Вы по всей вероятности не хотите).

то, Что мы обычно используем в тех случаях, является "Оптимистической Блокировкой". Django ORM не поддерживает это, насколько я знаю. Но была некоторая дискуссия о добавлении этой опции.

, Таким образом, Вы самостоятельно. В основном то, что необходимо сделать, добавляет поле "версии" к модели и передает ее пользователю как скрытое поле. Нормальный цикл для обновления:

  1. считывает данные и показывают его пользователю
  2. , пользователь изменяет данные
  3. пользовательское сообщение данные
  4. , приложение сохраняет его назад в базе данных.

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

можно сделать это с единственным вызовом SQL с чем-то как:

UPDATE ... WHERE version = 'version_from_user';

Этот вызов обновит базу данных, только если версия является все еще тем же.

28
ответ дан S.Lott 24 November 2019 в 10:59
поделиться

Для сейфа, база данных должна поддерживать транзакции .

, Если поля "свободная форма", например, текст и т.д. и необходимо позволить нескольким пользователям быть в состоянии отредактировать те же поля (у Вас не может быть владения отдельного пользователя к данным), Вы могли хранить исходные данные в переменной. Когда пользователь фиксирует, проверьте, изменились ли входные данные от исходных данных (в противном случае, Вы не должны беспокоить DB путем перезаписи старых данных), если исходные данные по сравнению с текущими данными в дб являются тем же, можно сохранить, если это изменилось, можно показать пользователю различие и спросить пользователя, что сделать.

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

я не знаю django, таким образом, я не могу дать Вам cod3s..;)

-2
ответ дан Stein G. Strindhaug 24 November 2019 в 10:59
поделиться

Другой вещью искать является "атомарное" слово. Атомарная операция означает, что Ваше изменение базы данных или произойдет успешно или перестанет работать, очевидно. Быстрый поиск показывает этот вопрос спрашивать об атомарных операциях в Django.

0
ответ дан Community 24 November 2019 в 10:59
поделиться

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

Что касается вашей реальной проблемы, когда несколько пользователей редактируют одни и те же данные ... да, используйте блокировку . ИЛИ:

Проверьте, для какой версии обновляется пользователь (делайте это безопасно, чтобы пользователи не могли просто взломать систему, чтобы сказать, что они обновляют последнюю копию!), И обновляйте только в том случае, если эта версия актуальна. В противном случае отправьте пользователю новую страницу с исходной версией, которую он редактировал, представленной версией и новой версией (-ами), написанной другими. Попросите их объединить изменения в одну, полностью обновленную версию. Вы можете попытаться объединить их автоматически, используя набор инструментов, например diff + patch, но вам все равно понадобится ручной метод объединения, работающий в случаях сбоя, так что начните с этого. Вас также' Мне нужно будет сохранить историю версий и разрешить администраторам отменять изменения на случай, если кто-то непреднамеренно или намеренно испортит слияние. Но вы, вероятно, все равно должны это иметь.

Скорее всего, существует приложение / библиотека django, которая сделает большую часть этого за вас.

1
ответ дан 24 November 2019 в 10:59
поделиться

Отсюда:
Как предотвратить перезапись объекта, измененного кем-то другим

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

def save(self):
    if(self.id):
        foo = Foo.objects.get(pk=self.id)
        if(foo.timestamp > self.timestamp):
            raise Exception, "trying to save outdated Foo" 
    super(Foo, self).save()
-6
ответ дан 24 November 2019 в 10:59
поделиться

Вот как я делаю оптимистическую блокировку в Django:

updated = Entry.objects.filter(Q(id=e.id) && Q(version=e.version))\
          .update(updated_field=new_value, version=e.version+1)
if not updated:
    raise ConcurrentModificationException()

Код, приведенный выше, может быть реализован в виде метода в Custom Manager.

Я делаю следующие предположения:

  • filter().update() приведет к одному запросу к базе данных, потому что фильтр ленивый
  • , а запрос к базе данных атомарный

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

ПРЕДУПРЕЖДЕНИЕ Django Doc:

Помните, что метод update() - это преобразованный непосредственно в SQL заявление. Это оптовая операция для прямые обновления. Он не запускает никаких save() методы на ваших моделях, или излучают сигналы pre_save или post_save

47
ответ дан 24 November 2019 в 10:59
поделиться

Для дальнейшего использования посетите https://github.com/RobCombs/django-locking . Он выполняет блокировку таким образом, чтобы не оставлять постоянных блокировок, путем сочетания разблокировки javascript, когда пользователь покидает страницу, и тайм-аутов блокировки (например, в случае сбоя браузера пользователя). Документация довольно полная.

3
ответ дан 24 November 2019 в 10:59
поделиться
Другие вопросы по тегам:

Похожие вопросы: