昨晚将我们的数据库从 9.3.5 升级到 9.4.1 后,服务器出现了高 CPU 峰值。升级是使用 pg_dump 完成的。于是把数据库转成SQL再导入9.4。
在 CPU 峰值期间,日志中有很多这样的消息:
process X still waiting for ExclusiveLock on extension of relation Y of database Z
after 1036.234 ms
和:
process X acquired ExclusiveLock on extension of relation Y of database Z
after 2788.050 ms
看起来可疑的是,有时在完全相同的毫秒内有多个“获取”消息用于完全相同的关系号。
为什么 Postgres 会在同一毫秒内将表增长两次?它可能是具有高填充因子的索引吗?
欢迎任何有关如何解决此问题的建议。
PS 我也在Postgres 邮件列表上问过这个问题,如果不妥请告诉我。
该问题与称为透明大页面 (THP) 的内核功能有关。您可以通过以下方式诊断
perf top
:该
compaction_alloc
函数指向一个问题。您可以通过以下方式关闭 THP:9.4 之前的 Postgres 版本没有特别要求大页面,但可以使用
always
.这是 RedHat 不鼓励 THP 用于数据库工作负载的链接。
转储-恢复周期会从表中删除所有膨胀和死元组,并以可能的最小大小进行恢复 - 除非您的
fillfactor
设置低于 100,从而为每个数据页保留一些回旋余地。迁移后,您会立即获得更多“扩展”(在表的物理末端添加页面(磁盘上的文件)。
积极的解决方案是在具有大量随机更新的表上设置
fillfactor
低于 100 。您可以在再次恢复之前在转储中执行此操作。由于您已经完成了迁移,您可能只是等待尘埃落定。通常,扩展变得不那么频繁,而重新引入摆动空间并在更新的表中使用死行版本。FILLFACTOR
对于具有大量随机更新的表,无论如何设置低于 100 可能是个好主意。以类似的方式应用于 btree 索引。但是保留的空间仅通过VACUUM FULL
或CLUSTER
(或转储-恢复周期)添加到现有数据页。更多关于
FILLFACTOR
,更新和VACUUM
: