前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >监控采集pg的autovacuum情况

监控采集pg的autovacuum情况

原创
作者头像
保持热爱奔赴山海
发布于 2025-05-09 07:04:17
发布于 2025-05-09 07:04:17
760
举报
文章被收录于专栏:数据库相关数据库相关

生产上,谁也不希望见到这种情况:

业务正处于高峰期,postgresql 反应很慢,监控显示磁盘IO很高,结果登陆机器发现居然是有大量的vaccum在吃磁盘IO。

对于这种情况,有必要提前监控预防。

思路

1 元数据采样SQL (注意,这个查询需要连接到PG主库执行,需要先切换到每一个需要采集的库里)

代码语言:txt
AI代码解释
复制
\c test
SELECT
	current_database() as dbname,
    pg_stat_all_tables.schemaname,
    pg_stat_all_tables.relname,
    -- pg_stat_all_tables.last_autovacuum,
    TO_CHAR(pg_stat_all_tables.last_autovacuum, 'YYYY-MM-DD HH24:MI:SS') as last_autovacuum,
    pg_total_relation_size(pg_class.oid) AS table_size
FROM
    pg_stat_all_tables
    JOIN pg_class ON pg_stat_all_tables.relid = pg_class.oid
WHERE 1=1
	AND pg_stat_all_tables.last_autovacuum is not null 
    AND NOT pg_class.relname LIKE 'pg\_%'
    AND NOT pg_class.relname LIKE'sql\_%'
	AND DATE(pg_stat_all_tables.last_autovacuum) >= DATE(NOW() - INTERVAL '3 day')  -- 只关注最近3天发生过autovacuum的表
	;


结果类似
 dbname | schemaname |     relname      |   last_autovacuum   | table_size 
--------+------------+------------------+---------------------+------------
 test   | public     | pgbench_accounts | 2025-05-09 14:00:06 |  138862592

2 创建MySQL表,用于存储上述巡检数据

代码语言:txt
AI代码解释
复制
drop table db_pg_autovacuum_monitoring;
CREATE TABLE db_pg_autovacuum_monitoring (
    id int unsigned not null auto_increment PRIMARY KEY,
    instance_cluster varchar(64) NOT NULL,
    dbname  varchar(64)  NOT NULL,
    schemaname  varchar(64)  NOT NULL,
    relname  varchar(64)  NOT NULL,
    last_autovacuum datetime,
    table_size BIGINT,
    capture_time datetime not null DEFAULT CURRENT_TIMESTAMP
) comment 'pg autovacuum 监控';

-- 加个唯一索引和时间列索引
alter table db_pg_autovacuum_monitoring add unique key uniq_union(instance_cluster ,dbname,schemaname,relname,last_autovacuum );
alter table db_pg_autovacuum_monitoring add index idx_capture_time(capture_time);

3 插入测试数据

代码语言:txt
AI代码解释
复制
insert into db_pg_autovacuum_monitoring (instance_cluster,dbname,schemaname,relname,last_autovacuum,table_size) 
values('test-pg','test','public','pgbench_accounts','2025-05-09 14:00:06',138862592);

insert into db_pg_autovacuum_monitoring (instance_cluster,dbname,schemaname,relname,last_autovacuum,table_size) 
values('test-pg','test','public','pgbench_accounts','2025-05-09 14:10:06',138862592);

insert into db_pg_autovacuum_monitoring (instance_cluster,dbname,schemaname,relname,last_autovacuum,table_size) 
values('test-pg','test','public','pgbench_accounts','2025-05-09 14:10:06',138862592);

insert into db_pg_autovacuum_monitoring (instance_cluster,dbname,schemaname,relname,last_autovacuum,table_size) 
values('test-pg','test','public','sbtest111','2025-05-09 14:10:06',138862592);

insert into db_pg_autovacuum_monitoring (instance_cluster,dbname,schemaname,relname,last_autovacuum,table_size) 
values('test-pg','test','public','sbtest111','2025-05-09 14:20:06',138862592);

4 分组统计,找出前一天全天周期内vacuum最频繁的几个表

代码语言:txt
AI代码解释
复制
-- 把capture_time调到一天前,便于下面的sql查询的演示
update db_pg_autovacuum_monitoring set capture_time = '2025-05-08 14:18:15';  


-- 分组统计,找出前一天全天周期内vacuum最频繁的几个表
SELECT
	instance_cluster,
	dbname,
	schemaname,
	relname,
	count(*) 
FROM
	db_pg_autovacuum_monitoring 
WHERE
	capture_time BETWEEN DATE_SUB( CURRENT_DATE, INTERVAL 1 DAY ) 
	AND DATE_SUB( CURRENT_DATE, INTERVAL 1 DAY ) + INTERVAL 1 DAY - INTERVAL 1 SECOND 
GROUP BY
	instance_cluster,
	dbname,
	schemaname,
	relname 
ORDER BY
	count(*) DESC 
	LIMIT 10;


效果类似:
+------------------+--------+------------+------------------+----------+
| instance_cluster | dbname | schemaname | relname          | count(*) |
+------------------+--------+------------+------------------+----------+
| test-pg          | test   | public     | pgbench_accounts |        5 |
| test-pg          | test   | public     | sbtest111        |        2 |
+------------------+--------+------------+------------------+----------+
2 rows in set (0.00 sec)

也就是说 pgbench_accounts 这个表在昨天做了最多次数的autovacuum。

大致流程就这些了,可以将上面逻辑用python封装下,和数据库平台结合,定时调度并计算和告警。

一些优化手段

1 优化业务操作

减少不必要的更新和删除

合并小事务

2 调整 autovacuum 配置参数

增大 autovacuum_naptime:

autovacuum_naptime 决定了 autovacuum 守护进程检查是否需要对表进行清理的时间间隔(单位为秒)。增大这个值会使 autovacuum 检查频率降低,从而减少其启动频率。在 postgresql.conf 文件中修改该参数:

代码语言:txt
AI代码解释
复制
autovacuum_naptime = 600  # 例如从默认的10秒改为600秒 

修改后需要重启 PostgreSQL 使配置生效。但要注意,设置过大可能导致数据库中死元组长时间积累,影响性能。

降低 autovacuum_max_workers:

autovacuum_max_workers 控制同时运行的 autovacuum 工作进程的最大数量。减少这个值意味着同一时间执行 autovacuum 操作的进程减少,从而降低对系统资源的占用,同时也会在一定程度上降低 autovacuum 的执行频率。在 postgresql.conf 文件中修改:

代码语言:txt
AI代码解释
复制
autovacuum_max_workers = 2  # 例如从默认的3个改为2个

同样,修改后需重启服务。但设置过小可能导致 autovacuum 处理效率低下,无法及时清理死元组。

3. 定期手动执行 VACUUM

定期执行 VACUUM ANALYZE:

在业务低峰期定期手动执行 VACUUM ANALYZE 操作。VACUUM 用于清理死元组并回收空间,ANALYZE 用于更新统计信息。手动执行这些操作可以在系统负载较低时完成清理工作,避免 autovacuum 在业务高峰期自动触发。例如,可以通过操作系统的 cron 任务在每天凌晨 2 点执行:

代码语言:txt
AI代码解释
复制
0 2 * * * psql -U your_username -d your_database -c "VACUUM ANALYZE;"

使用 VACUUM FULL(高危操作,你知道自己在做什么吗!!):

VACUUM FULL 比普通的 VACUUM 更激进,它会重写整个表,将表中的数据重新整理并压缩,能更有效地清理空间和减少碎片化。但它会对表加排他锁,期间表不可读写。可以在维护窗口定期执行,例如:

代码语言:txt
AI代码解释
复制
VACUUM FULL your_table;

由于其对业务的影响较大,所以只适用于对可用性要求不高的表,并且要在业务低谷期执行。

4. 调整事务隔离级别

选择合适的事务隔离级别:

在开始事务时指定隔离级别:

代码语言:txt
AI代码解释
复制
    BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED;
    -- 业务操作
    COMMIT;

参考文章: DBA 失职导致 PostgreSQL 日志疯涨 (公众号 Austindatabases )

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Pg数据库日常维护操作指南
本文主要用来记述pg数据库的相关操作和异常排查指南,继上一篇博客之后,异常的频繁更新,导致死亡元组指数级增长之后,空间占用也成倍增长,逻辑问题导致了数据库问题,但细想之下也发现,当pg在面对海量数据的更新删除之后,频繁的autovacuum会导致数据库大量的I/O,完了又会影响其他进程,就参数配置来看,还是有蛮多优化的空间的,毕竟空间和时间是两个相生相克的关系。就目前的默认的配置来看,手动标记60w数据执行vacuum标记清理花了6分钟,直接清空死亡元组也差不多这个时间,当空间膨胀到300g的时候数据量达到140w,vacuum已经有点吃不消了执行了半个小时也没有看到执行结束,至少在频繁更新的情况下,可见vacuum还是有他的局限性,就像官网提示的:Plain VACUUM may not be satisfactory when a table contains large numbers of dead row versions as a result of massive update or delete activity. 而且默认配置的的自动间隔是1分钟,我觉得这里面有很大的优化空间,尤其是海量数据频繁更新和删除的时候,当autovacuum的执行时间超过1分钟之后,就需要注意系统的死亡元组数量了,类似于当我打扫垃圾的速度低于产生垃圾的速度此时垃圾只会越来越多,当然这是在大数据量特定频繁更新和删除场景的情况下,结合相关的配置产生的一种思考。 需要注意的配置主要有autovacuum_max_workers可以根据cpu核心数配置,autovacuum_work_mem工作内存和vacuum_scale_factor规模因子,
查拉图斯特拉说
2023/10/25
6100
Postgresql备库复制冲突原理
报错是备库事务或者单SQL查询时间长,和备库的日志apply发生冲突,如果业务上有长事务、长查询,主库上又再修改同一行数据,很容易造成备库的wal日志无法apply。
mingjie
2022/05/12
1.3K0
PostgreSQL技术大讲堂 - 第18讲:Tuning Autovacuum
PostgreSQL从小白到专家,是从入门逐渐能力提升的一个系列教程,内容包括对PG基础的认知、包括安装使用、包括角色权限、包括维护管理、、等内容,希望对热爱PG、学习PG的同学们有帮助,欢迎持续关注CUUG PG技术大讲堂。
用户5892232
2023/06/12
4720
PostgreSQL autovacuum 5 怎么监控(autovacuum 扫描表工作的百分比)
PostgreSQL 最大的问题就是vacuum,只要PG的实现多版本和UNDO的方式不改变,那么这个话题就会一直继续,到永远。
AustinDatabases
2021/10/27
8290
PostgreSQL autovacuum 5   怎么监控(autovacuum 扫描表工作的百分比)
Prometheus+Grafana PG监控部署以及自定义监控指标
Prometheus:是从云原生计算基金会(CNCF)毕业的项目。Prometheus是Google监控系统BorgMon类似实现的开源版,整套系统由监控服务、告警服务、时序数据库等几个部分,及周边生态的各种指标收集器(Exporter)组成,是在当下主流的监控告警系统。
数据和云
2021/08/27
4.4K0
Prometheus+Grafana PG监控部署以及自定义监控指标
vacuum full空间不释放的原因及过程模拟
vacuum full本质上是创建了一张新的表,会创建该表的一个新拷贝,并且在操作完成之前都不会释放旧的拷贝。因此在进行vacuum full操作的时候是会加上一个ACCESS EXCLUSIVE级别的锁,所以一般只有当我们需要从表中回收大量磁盘空间的,即膨胀率很高的表才会去做vacuum full的操作。
AiDBA宝典
2023/04/27
1.7K0
vacuum full空间不释放的原因及过程模拟
POSTGRESQL AUTO_VACUUM 弄清问题,解决问题
​弄清楚POSTGRESQL 的VACUUM 对于维护好POSTGRESQL 和 理解一些在基于POSTGRESQL 设计中的"点" 是有必要性的. 虽然数据库是有包容性的,但他有他自己的"脾气", 顺毛驴,如果你非要呛着他,踢你一脚也让你缓不过来.
AustinDatabases
2021/01/07
9240
PG使用插件pg_squeeze解决表和索引的膨胀问题
PostgreSQL中大量更新或者删除记录后,加上autovacuum参数未做优化或设置不当,会导致表及索引膨胀。生产环境除了手动使用vacuum之外,还有两个比较常用的工具:一个是pg_repack,另外一个是pg_squeeze。
AiDBA宝典
2023/04/27
1.8K0
PG使用插件pg_squeeze解决表和索引的膨胀问题
PostgreSQL 难搞的事系列 --- vacuum 的由来与PG16的命令的改进 (1)
开头还是介绍一下群,如果感兴趣PolarDB ,MongoDB ,MySQL ,PostgreSQL ,Redis, Oceanbase, Sql Server等有问题,有需求都可以加群群内有各大数据库行业大咖,CTO,可以解决你的问题。加群请联系 liuaustin3 ,在新加的朋友会分到2群(共1720人左右 1 + 2 + 3 + 4+5) 另欢迎 OpenGauss GAUSSDB的技术人员加入
AustinDatabases
2023/11/17
3790
PostgreSQL  难搞的事系列 --- vacuum 的由来与PG16的命令的改进 (1)
优化PG查询:一问一答
可以使用Postgres Exporter采集PG的各种指标,并将其发送给普罗米修斯。更多详细信息参考:
yzsDBA
2021/09/29
1.6K0
PostgreSQL 远程管理越来越简单,6个自动化脚本开胃菜
Node.js 今天开始搞这个,原因很简单,因为要写程序对数据库进行管理,但我不想使用麻烦的Python, 超高难度的Go, Node.js正是一个写脚本的好工具,且部署简单,今天我们就开始部署Node.js且用他来管理一些PostgreSQL.
AustinDatabases
2024/11/25
1660
PostgreSQL 远程管理越来越简单,6个自动化脚本开胃菜
Postgresql垃圾回收Vacuum优化手册
为什么慢分析:https://www.postgresql.org/docs/14/progress-reporting.html#VACUUM-PROGRESS-REPORTING
mingjie
2022/12/02
7110
Greenplum 7 新特性整理
参考:https://www.xmmup.com/zaidockerzhongkuaisutiyangreenplum-7-0-0.html
AiDBA宝典
2023/10/16
1.4K0
Greenplum 7 新特性整理
PostgreSQL autovacuum 优化与调试 (1 触发 autovacuum 的条件)
PostgreSQL 的数据库系统中是需要进行autovacuum 进行表级别的数据清理的。在开始autovacuum 进行调优之前实际上是需要理解为什么需要autovacuum.
AustinDatabases
2021/10/14
1.8K0
PostgreSQL autovacuum 优化与调试 (1 触发 autovacuum 的条件)
POSTGRESQL analyze table 到底做了什么与扩展统计
PostgreSQL 中对表的状态是有单独的命令来进行状态的收集的,到底怎么对表来进行状态的收集,并且都做了什么,我们怎么来依靠这些信息来对查询进行有益的帮助。这些都将在这篇文章里面探讨。
AustinDatabases
2021/06/10
3.3K0
POSTGRESQL  analyze  table 到底做了什么与扩展统计
PgSQL技术内幕-Analyze做的那些事-pg_stat_all_tables
PgSQL技术内幕-Analyze做的那些事-pg_stat_all_tables
yzsDBA
2023/11/27
5390
PgSQL技术内幕-Analyze做的那些事-pg_stat_all_tables
PG基于dexter的自动化索引推荐
github地址: https://github.com/ankane/dexter
保持热爱奔赴山海
2024/01/03
3120
PostgreSql Postgresql 监控你说了不算,谁说了算 ? (5 整理的一些脚本)
一写就写到了第五期,有点写连续剧的味道,可能会有第六期,我想是,今天的内容并不是某些工具,其实工具也是根据数据库的原理,通过各种方式获得数据。那怎么通过PG中的系统表来获得数据就是这期的重点。
AustinDatabases
2020/07/16
7290
PostgreSql  Postgresql 监控你说了不算,谁说了算 ? (5  整理的一些脚本)
Postgresql之autovacuum worker
PostgreSQL数据库为了定时清理因为MVCC 引入的垃圾数据,实现了自动清理机制。其中涉及到了两种辅助进程:
DB之路
2021/03/05
1.2K0
PostgreSQL统计信息的几个重要视图
比如tup_returned值明显大于tup_fetched,历史SQL语句很多是全表扫描,存在没有使用索引的SQL,可结合pg_stat_statments查找慢SQL,也可结合pg_stat_user_table找全表扫描次数和行数最多的表;
yzsDBA
2020/10/29
1.3K0
推荐阅读
相关推荐
Pg数据库日常维护操作指南
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档