我们正在运行一个平均有 10k 活跃用户的网络应用程序,由 6 个网络节点提供服务,并由 Postgres 9.4.6 提供支持。
我们的监控工具发现了以下运行缓慢的查询,该查询通常具有不可接受的响应时间,在过去几天偶尔会导致中断。
这是一个小表,基本上是内部序列实现(遗留应用程序),跟踪每个其他表的唯一 ID:
CREATE TABLE ids_for_records
(
tableid integer NOT NULL,
id bigint NOT NULL,
CONSTRAINT ids_for_records_pk PRIMARY KEY (tableid)
)
WITH (
OIDS=FALSE
);
该表只有大约 200 条记录。我们的 webapp 节点使用这个查询来获取一批专门供自己使用的 ID:
UPDATE ids_for_records
SET id = id + <batchsize>
WHERE tableid = <unique-internal-table-id>
RETURNING id;
我需要找出为什么上述查询的性能在过去几天显着下降:平均大约 1 秒,但有时也需要 30-60 秒。在高负载期间,所有节点都在并行地对多个连接执行完全相同的查询。
更新:查询由单个(慢)查询持有的锁(来自 pg_lock、pg_class 和 pg_stat_activity)的信息表明,它与正在等待的其他事务的查询完全相同。因此,我们有同时尝试更新(增加 ID 值)同一行的事务,因此一个具有所有所需锁的活动会阻塞所有其他的。
否则数据库是健康的,我们的运营团队没有发现任何关于存储、内存或连接的问题;然而,另一个表的大小最近达到了 64GB,这可能是相关的。
有谁知道什么会导致这种性能下降?与以前相同的负载,但这个瓶颈查询比以前慢了约 5 倍。