首页 > 解决方案 > Postgres auto-vacuum 不会回收死元组空间导致磁盘已满问题

问题描述

我有一个用例,每分钟同时在另一端插入 100 000 行,少数线程会获取这些行并将它们从我的表中删除。所以肯定会在我的表中创建很多死元组。

我的自动真空配置是

autovacuum_max_workers = 3
autovacuum_naptime = 1min
utovacuum_vacuum_scale_factor = 0.2
autovacuum_analyze_scale_factor = 0.1
autovacuum_vacuum_cost_delay = 20ms
autovacuum_vacuum_cost_limit = -1

从“pg_stat_user_tables”我可以发现自动真空正在我的表上运行,但在几个小时内我的磁盘将满(500 GB),我无法插入任何新行。

在第二次尝试时,我更改了以下配置

autovacuum_naptime = 60min
autovacuum_vacuum_cost_delay = 0

这次我的模拟和自动真空运行良好,最大磁盘大小为 180 GB。

这里我的疑问是,如果我将“autovacuum_vacuum_cost_delay”更改为零毫秒,自动真空如何释放死元组空间并 PG 重用它?如果我将值设置为 20 毫秒,为什么它不能按预期工作?

标签: postgresqlpostgresql-9.6autovacuum

解决方案


这里我的疑问是,如果我将“autovacuum_vacuum_cost_delay”更改为零毫秒,自动真空如何释放死元组空间并 PG 重用它?

真空释放的空间记录在可用空间映射中,从那里分发以供将来的 INSERT 重复使用。

另一个要补充的细节是,在 9.6 中,只有在整个表本身被完全清空后才会清空可用空间映射,因此直到那时才能找到释放的空间。如果 VACUUM 由于太慢或被中断而永远无法完成,那么它释放的空间将不会被重新用于 INSERT。这在 v11 中得到了改进。

如果我将值设置为 20 毫秒,为什么它不能按预期工作?

因为真空跟不上那个值。PostgreSQL 的默认值通常只适用于较小的服务器,而您的服务器似乎并不适用。在这种情况下更改默认值是适当且可取的。请注意,在 v12 中,默认值从 20 降低到 2(其类​​型也相应地从 int 更改为 float,因此您现在可以更精确地指定值)


推荐阅读