相关疑难解决方法(0)

django的竞争条件

以下是具有潜在竞争条件的django视图的简单示例:

# myapp/views.py
from django.contrib.auth.models import User
from my_libs import calculate_points

def add_points(request):
    user = request.user
    user.points += calculate_points(user)
    user.save()
Run Code Online (Sandbox Code Playgroud)

竞争条件应该是相当明显的:用户可以两次发出此请求,并且应用程序可能user = request.user同时执行,导致其中一个请求覆盖另一个请求.

假设函数calculate_points相对复杂,并且基于各种奇怪的东西进行计算,这些东西不能放在一个单独的update并且很难放入存储过程中.

所以这是我的问题:django可以使用哪种锁定机制来处理类似的情况?

python database django locking race-condition

35
推荐指数
4
解决办法
1万
查看次数

如何在Django中使用唯一检查来避免竞争条件

我有一个简单的模型:

class InvitationRequest(models.Model):
    email = models.EmailField(max_length=255, unique=True)
Run Code Online (Sandbox Code Playgroud)

一个简单的模型形式:

class InvitationRequestForm(forms.ModelForm):
    class Meta:
        model = InvitationRequest
Run Code Online (Sandbox Code Playgroud)

现在,假设我尝试以标准方式处理它:

form = InvitationRequestForm(request.POST)
if form.is_valid():
    form.save()
Run Code Online (Sandbox Code Playgroud)

存在竞争条件,因为验证执行简单SELECT查询以确定是否已经存储了这样的电子邮件,并且如果一切正常,则它继续进行form.save().如果有一个并发进程在同一时刻执行相同操作,则两个表单都将验证,并且两个进程都将调用,form.save()因此一个将成功,另一个将失败导致IntegrityError.

处理这个问题的标准方法是什么?

我希望在表单对象中有一个标准错误,因此我可以将其传递给模板并通知用户该问题.

我知道:

  • 我可以使用try/except包装所有内容并手动将新错误添加到我的表单中
  • 我可以用SERIALIZABLE事务包装所有东西(在MySQL中,因为它执行下一个键锁定每次选择)
  • 我可以使用覆盖Model._perform_unique_checks并使其使用select_for_update(由于下一个键锁定,与MySQL一起使用)
  • 我可以获得表级独占锁

这些解决方案都没有吸引力,我也使用PostgreSQL,它与MySQL在这个领域不同.

python mysql django postgresql validation

4
推荐指数
2
解决办法
1617
查看次数