【问题标题】:Occasional IntegrityError on m2m fields using PostgreSQL使用 PostgreSQL 的 m2m 字段偶尔出现 IntegrityError
【发布时间】:2012-10-22 09:16:27
【问题描述】:

我无法检测到任何模式,在某个模型的每 1000 次编辑中可能有 1 次在 m2m 字段上返回 IntegrityError。大多数时候,这个字段甚至没有被修改。保存模型时,我相信 django 总是擦除 m2m 字段,然后重新添加项目,对吗?我看到 django 打电话给clear() 然后add()s 这些项目。

然后我的代码失败了:

IntegrityError:重复键值违反唯一约束 “app_model_m2m_field_key”详细信息:键(model1_id,model2_id)=(597, 1009) 已经存在。

好像物品的添加是在物品被清除之前进行的,这很奇怪。我试图重现它,但它非常困难,只是偶尔发生。知道是什么原因造成的吗?也许设置自动提交可以解决这个问题?

提前致谢

【问题讨论】:

    标签: django postgresql


    【解决方案1】:

    很可能,您有两个请求竞相同时提交类似的更改。

    1. 请求 1 开始事务并删除现有的 M2M 行。

    2. 请求 2 开始一个事务并使用相同的 where 子句删除 M2M 行。这会阻塞等待请求 1 的事务提交。

    3. 请求 1 重新插入所有 M2M 行并提交。

    4. 请求 2 恢复,删除成功,没有删除任何行,因为语句开始时存在的所有行都已被删除。

    5. 请求 2 尝试重新插入 M2M 行,但数据库检测到它已经存在并返回错误。

    可以通过升级到 SERIALIZABLE isolation level(而不是 PostgreSQL 的默认 READ COMMITTED)来解决此问题,但代价是更令人兴奋的潜在故障模式和更差的性能。

    我假设你是对的,Django 执行 DELETE,然后执行一系列 INSERT,尽管这不是一个很好的计划,因为它加剧了这种竞争。

    最好的计划是确定实际发生了哪些更改,并且只要求数据库进行这些更改,因为如果您遇到完整性错误,那是因为存在真正的冲突,您可能无论如何也无能为力。

    【讨论】:

      猜你喜欢
      • 2011-02-24
      • 2014-03-09
      • 2011-03-02
      • 2017-06-12
      • 1970-01-01
      • 1970-01-01
      • 2011-01-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多