在Django / Postgresql中调试活锁

我使用postgresql_psycopg2数据库后端在Apache2,mod_python和PostgreSQL 8.3上运行Django上适度流行的Web应用程序。我偶尔遇到活锁,当apache2进程持续消耗99%的CPU几分钟或更长时间时,可以识别。 我在apache2进程上做了一个strace -ppid,发现它不断重复这些系统调用:
sendto(25, "QSSELECT (1) AS "a" FROM "account_profile" WHERE "account_profile"."id" = 66201 ", 84, 0, NULL, 0) = 84
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
poll([{fd=25, events=POLLIN|POLLERR, revents=POLLIN}], 1, -1) = 1
recvfrom(25, "E210SERRORC25P02Mcurrent transaction is aborted, commands ignored until end of transaction blockFpostgres.cL906Rexec_simple_queryZ5E", 16384, 0, NULL, NULL) = 143
这个确切的片段在跟踪中不断重复,并且在我最终杀死apache2进程之前运行了超过10分钟。 (注意:我编辑了这个以替换我之前的strace片段,其中一个新的片段显示完整的字符串内容而不是截断。) 我对上面的解释是django试图在我的表account_profile上进行存在检查,但是在某些早期点(在我开始跟踪之前)出现了问题(SQL解析错误?参照完整性或唯一性约束违规?谁知道? ),现在Postgresql返回错误“当前事务被中止”。出于某种原因,它不是提出异常并放弃,而是继续重试。 一种可能性是在调用Profile.objects.get_or_create时触发此操作。这是映射到account_profile表的模型类。也许get_or_create中有一些东西可以捕获过多的异常并重试?从Web服务器日志中,可能是因为双击站点注册表单中的POST按钮而发生此活锁。 这个情况在过去的几天里在现场发生了几次,并且在我介入之前导致了显着的减速,所以除了无限的死锁之外的任何其他事情都会有所改善! :)     
已邀请:
结果证明这完全是我的错。我找到了
select (1) as 'a'
语句似乎起源的地方(在
django/models/base.py
)并且将其砍掉以记录回溯,这清楚地指出了我的代码。 我有一些代码构成了每个配置文件的唯一电子邮件“密钥”。这些键是随机生成的,所以因为有一些重叠的可能性,我在try / run中运行它。我的假设是,如果密钥不是唯一的,数据库的唯一约束会导致保存失败,我可以再试一次。 不幸的是,在Postgresql中,您不能简单地在完整性错误后再试一次。您必须再次尝试之前发出COMMIT或ROLLBACK命令(即使您处于自动提交模式)。所以我有一个无限循环的失败保存尝试,我忽略了错误消息。 现在我寻找一个更具体的异常(
django.db.IntegrityError
)并运行有限数量的尝试,以便循环不是无限的。 感谢大家观看/回答。     
你的分析听起来不错。显然,它没有意识到交易中止的事实。我建议你把这个报告为django项目的一个bug ...     

要回复问题请先登录注册