【问题标题】:Debugging livelock in Django/Postgresql在 Django/Postgresql 中调试活锁
【发布时间】:2011-01-02 03:23:58
【问题描述】:

我在 Django 上使用 Apache2、mod_python 和 PostgreSQL 8.3 以及 postgresql_psycopg2 数据库后端运行一个中等流行的 Web 应用程序。当 apache2 进程在几分钟或更长时间内持续消耗 99% 的 CPU 时,我偶尔会遇到活锁。

我在apache2进程上做了一个strace -ppid,发现它一直在重复这些系统调用:

sendto(25, "Q\0\0\0SSELECT (1) AS \"a\" FROM \"account_profile\" WHERE \"account_profile\".\"id\" = 66201 \0", 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, "E\0\0\0\210SERROR\0C25P02\0Mcurrent transaction is aborted, commands ignored until end of transaction block\0Fpostgres.c\0L906\0Rexec_simple_query\0\0Z\0\0\0\5E", 16384, 0, NULL, NULL) = 143

这个确切的片段在跟踪中不断重复,并且在我最终终止 apache2 进程之前运行了 10 多分钟。 (注意:我对此进行了编辑以用一个新的 strace 片段替换我之前的 strace 片段,该片段显示完整的字符串内容而不是截断。)

我对上述内容的解释是 django 正在尝试对我的表 account_profile 进行存在检查,但在较早的时间点(在我开始跟踪之前)出现了问题(SQL 解析错误?违反引用完整性或唯一性约束?谁知道?),现在 Postgresql 正在返回错误“当前事务已中止”。出于某种原因,它没有引发异常并放弃,而是不断重试。

一种可能性是,这是在调用 Profile.objects.get_or_create 时触发的。这是映射到 account_profile 表的模型类。也许 get_or_create 中有一些东西旨在捕获过于广泛的异常并重试?从网络服务器日志来看,这个活锁可能是由于双击我网站注册表单中的 POST 按钮造成的。

这种情况在过去几天在现场发生了几次,在我进行干预之前导致速度显着下降,所以除了无限死锁之外,几乎所有的事情都会有所改善! :)

【问题讨论】:

  • 无用的技术吹毛求疵:这并不是真正的“活锁”——该术语指的是双方不断调整自己的状态以试图适应对方,但双方都无法推进的情况进一步。但是在您的情况下,PostgreSQL 处于永久错误状态。我会称之为挂起或无限循环。

标签: django postgresql transactions psycopg2 livelock


【解决方案1】:

结果证明这完全是我的错。我找到了select (1) as 'a' 语句似乎起源的位置(在django/models/base.py 中)并破解了它以记录回溯,它清楚地指向了我的代码。

我有一些代码可以为每个配置文件组成一个唯一的电子邮件“密钥”。这些键是随机生成的,所以因为有一些重叠的可能性,所以我在一个 while 循环内的 try/except 中运行它。我的假设是,如果密钥不是唯一的,数据库的唯一约束会导致保存失败,我可以再试一次。

不幸的是,在 Postgresql 中,您不能简单地在完整性错误后重试。在重试之前,您必须发出 COMMIT 或 ROLLBACK 命令(即使您显然处于自动提交模式)。所以我有一个无限循环的失败保存尝试,我忽略了错误消息。

现在我寻找一个更具体的异常 (django.db.IntegrityError) 并运行有限次数的尝试以使循环不是无限的。

感谢大家观看/回答。

【讨论】:

    【解决方案2】:

    你的分析听起来不错。显然,它没有发现交易被中止的事实。我建议您将此作为错误报告给 django 项目...

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多