2

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

然后我的代码失败了:

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

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

提前致谢

4

1 回答 1

3

最有可能的是,您有两个请求同时提交类似的更改。

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

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

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

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

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

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

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

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

于 2012-11-01T21:55:03.227 回答