【问题标题】:Django locking between clean() and save()Django 在 clean() 和 save() 之间锁定
【发布时间】:2013-08-28 08:13:52
【问题描述】:

假设我有一个具有唯一字段电子邮件的模型:

class MyModel:

    email = models.EmailField(unique=True)

    def save(self):
        .... # save model

    def clean(self):
        .... # validate model, make sure email doesn't already exist.

通常,如果浏览器提交一个表单,其中 email 是一个已经存在的值,由于模型表单字段验证,它会引发 ValidationError。

如果两个浏览器同时提交同一封电子邮件,其中 email 是一个尚不存在的值,则至少有一个请求会通过将一行保存到数据库中来成功。另一个请求,如果它在第一个请求之后到达足够长的时间,将被正常处理 - 引发 ValidationError 表示电子邮件已经存在。但如果它与第一个几乎同时到达,那么clean() 将成功 - 电子邮件尚不存在,但在执行save() 方法时,来自第一个请求的行将有被保存。在后一种情况下,将引发 IntegrityError,服务器将返回 Internal Server 500 错误,这是不希望的。

如何防止最后一种情况发生?数据库事务?

【问题讨论】:

    标签: python django


    【解决方案1】:

    在这种情况下仅使用 Django 数据库事务是不够的。创建新模型时要做的是将数据库表锁与事务一起使用。但是 Django 还没有用于锁定表的 API,因此您必须使用原始 SQL 为您的数据库执行关于其类型的表锁定。

    如果你使用 PostgreSQL,这里有一个完美的例子: http://www.caktusgroup.com/blog/2009/05/26/explicit-table-locking-with-postgresql-and-django/

    如果你在其他数据库下,你将不得不研究如何执行表锁定。

    【讨论】:

    【解决方案2】:

    虽然用例略有不同,但您可能需要阅读 Alex Martelli 的 this old answer 关于“乐观并发”方法的内容。

    【讨论】:

      猜你喜欢
      • 2012-02-21
      • 1970-01-01
      • 1970-01-01
      • 2011-08-19
      • 1970-01-01
      • 2017-01-31
      • 1970-01-01
      • 2016-01-08
      • 1970-01-01
      相关资源
      最近更新 更多