使用PostgreSQL在m2m字段上偶尔出现IntegrityError

时间:2012-11-01 18:02:57

标签: django postgresql

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

我的代码失败了:

  

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

似乎在项目清除之前执行了项目添加,这非常奇怪。我试图重现它,但它很难,只偶尔发生。知道是什么原因引起的吗?也许设置自动提交可以解决这个问题?

提前致谢

1 个答案:

答案 0 :(得分:3)

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

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

  2. 请求2开始一个事务并删除具有相同where子句的M​​2M行。这会阻止等待请求1的事务提交。

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

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

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

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

    我认为你是对的,Django正在执行DELETE,然后执行一系列INSERT,虽然这不是一个非常好的计划,正是因为它加剧了这种竞争。

    最好的计划是确定实际发生了什么变化,并且只要求数据库进行这些更改,因为如果您收到完整性错误,那就是因为存在真正的冲突,您可能无论如何都无法做任何事情。 / p>