Postgres 有时会挂起

Postgres 有时会挂起

我们正在使用 Postgres 作为 Django 项目的数据库后端。除了 Postgres 偶尔会挂起之外,一切都运行良好。平均负载峰值达到 80 点,并且有许多 posgtres 进程。据我所知,问题在于我们的在线用户表。每次请求都有更新,我们正在更新“上次看到”列。每分钟都有 cronjob 删除 1 分钟内不活跃的用户。例如,今天,当 Postgres 挂起时,我看到这个表上有很多更新和删除。我认为这是某种竞争条件?

这张包含在线用户的表并不大。高峰时段大约有 800 条记录。以下是架构。

   Column   |           Type           |                            Modifiers                            
------------+--------------------------+-----------------------------------------------------------------
 id         | integer                  | not null default nextval('spoleczniak_online_id_seq'::regclass)
 postac_id  | integer                  | not null
 data       | timestamp with time zone | not null
 zalogowany | timestamp with time zone | not null
Indexes:
    "spoleczniak_online_pkey" PRIMARY KEY, btree (id)
    "spoleczniak_online_postac_id_key" UNIQUE CONSTRAINT, btree (postac_id)
    "spoleczniak_online_data" btree (data)
Foreign-key constraints:
    "spoleczniak_online_postac_id_fkey" FOREIGN KEY (postac_id) REFERENCES postac_postacie(id) DEFERRABLE INITIALLY DEFERRED

通常情况下,Postgres 产生的负载平均点数少于 1.5。我们在 i7、16 GB RAM 和硬件 RAID-10(3x2 磁盘)上运行它,用于 OS/数据 + RAID-1(2 磁盘)用于 WAL。硬件 RAID 有 512 MB 的缓存。

我已经尝试了 9.0 和 9.1 beta(我甚至在 9.1 中没有为该表设置 WAL 日志)。

我确实在考虑转向 MySQL,但不知道任何转换工具。:P

PS. 我不知道它更适合 Serverfault 还是 Stackoverflow... 但正如你所见,我决定把它放在 Serverfault 上。:P

编辑:

来自日志的一些信息:

Jul 31 20:37:16 postgres postgres[1420]: [3-1] LOG:  00000: process 1420 acquired ExclusiveLock on tuple (29,7) of relation 33107 of database 20005 after 2071.481 ms
Jul 31 20:37:16 postgres postgres[1420]: [3-2] LOCATION:  ProcSleep, proc.c:1076
Jul 31 20:37:16 postgres postgres[1420]: [3-3] STATEMENT:  UPDATE "spoleczniak_online" SET "postac_id" = 101651, "data" = '2011-07-31 20:39:18.000699', "zalogowany" = '2011-07-31 20:31:04.843741' WHERE "spoleczniak_online"."id" = 559650 
Jul 31 20:37:16 postgres postgres[1493]: [3-1] LOG:  00000: process 1493 acquired ExclusiveLock on tuple (29,7) of relation 33107 of database 20005 after 1393.154 ms
Jul 31 20:37:16 postgres postgres[1493]: [3-2] LOCATION:  ProcSleep, proc.c:1076
Jul 31 20:37:16 postgres postgres[1493]: [3-3] STATEMENT:  UPDATE "spoleczniak_online" SET "postac_id" = 101651, "data" = '2011-07-31 20:39:15.646537', "zalogowany" = '2011-07-31 20:31:04.843741' WHERE "spoleczniak_online"."id" = 559650 

好的,这是锁定问题...但我该如何避免呢?

答案1

这似乎是锁定问题:一些大型查询锁定过多,因此其他正在运行的查询无法完成,直到释放锁定。打开慢速查询日志记录,添加更多监控。我强烈建议使用一些监控系统(zabbix、zenoss 等)来了解您的 postgresql 数据库状态。

作为快速“监控”,请在挂起期间查看 pg_stat_activity 和 pg_locks 视图。下面是我经常使用的一个很好的查询:

SELECT
  datname, 
  NOW() - query_start AS duration, 
  procpid, 
  current_query 
FROM
  pg_stat_activity 
WHERE
    current_query <> '<IDLE>'
  AND
    NOW() - query_start > '1 second'
ORDER BY duration DESC;

它通常会提供足够的信息,但有时我必须运行更多才能了解发生了什么。

请使用此查询(或类似查询)的输出更新您的问题。

答案2

我会推荐这本书PostgreSQL 9.0 高性能第 11 章“数据库活动和统计信息”。解决这个问题的另一个好地方是 postgresql-performance 邮件列表。

相关内容