2

我的模型:

class Order(models.Model):
    property_a = models.CharField()
    property_b = models.CharField()
    property_c = models.CharField()

许多用户将在短时间内通过管理员更改页面访问给定记录,因此我遇到了并发问题:

用户 1 和 2 同时打开更改页面。假设加载页面时所有值都是空白的。用户 1 将 property_a 设置为“a”,将 property_b 设置为“b”,然后保存。一秒钟后,如果用户 2 更改属性 b 并且 c 然后保存,它将悄悄地覆盖用户 1 的所有值。在这种情况下,property_a 将恢复为空白,而 b 和 c 将是用户 2 输入的任何值。

我需要有关如何处理此问题的建议。如果我必须在模型中有一个版本字段,我如何将它传递给管理员,我在哪里进行检查,以便我可以优雅地通知用户他们的更改无法保存,因为另一个用户修改了记录?有没有比只向用户返回错误更无缝的方法?

4

1 回答 1

0

标准解决方案是防止您的用户共享单个记录。完全不清楚为什么这么多用户会搞乱完全相同的Order实例。

考虑这Order可能是一个复合对象,并且您在单个模型中投入了太多。这是第一个 - 也是最好的 - 解决方案。

如果(出于莫名其妙的原因)您不会分解它,那么您必须创建一个两部分更新事务。

  1. 重新查询数据。与针对该用户会话所做的原始查询进行比较。

  2. 如果数据与原始查询不匹配,则其他人对其进行了更改。用户的更改无效、回滚、清除,用户会看到一个新的查询。

  3. 如果数据确实匹配,您可以尝试提交更改。

上述算法有一个竞态条件,通常通过低级 SQL 解决。请注意,它会使用户的工作无效,从而最大程度地刺激用户。

这就是为什么您的首选是分解模型以消除并发性。


我的模型有一个杂项注释字段

这是一个糟糕的设计。(a) 该领域的冲突破坏了并发性。(b) 没有评论记录或历史记录。

(b) 项表示行为不端的用户可能恶意破坏此数据。如果您将注释和评论保存为日志,原则上您可以限制用户仅更改他们自己的评论。

[在大多数带有“杂项注释”的数据库中,该字段已成为一项成本高昂、难以维护的责任,其中充满了重要但无法解析的数据。杂项说明是用户在应用软件之外发明自己的流程的地方。]

“杂项注释”必须像日志一样处理,附有无限数量的注释——带有日期戳——由用户识别——附加到订单上。

如果您只是对设计进行分区以将注释放在单独的表中,那么您就可以解决并发问题。

于 2010-06-25T01:38:50.140 回答