背景

不知道从何时开始,数据库空载时的性能消耗越来越高,当业务高峰期,CPU 和内存都处于高负载的情况下,观看 AWS 的监控,发现负载空载时占用很高。

并且占用较高的 Top5 分为为:

autovacuum: VACUUM ANALYZE pg_catalog.pg_attribute
autovacuum: VACUUM ANALYZE pg_catalog.pg_type
autovacuum: VACUUM ANALYZE pg_catalog.pg_depend
autovacuum: VACUUM ANALYZE pg_catalog.pg_class
autovacuum: VACUUM ANALYZE pg_catalog.pg_index

由上面的 Top5 可以得知,目前数据库的负载较高,都是由于 PgSql 系统表的 VACUUM 导致的,但是,为什么会出现这种情况呢?我们一起来慢慢解决这个问题吧!

问题排查

排查方向

VACUUM 是 PgSql 的一种垃圾回收机制,主要用于清理数据库中的不再需要的行(也称为“死亡行”或“dead tuples”),并且它回收这些行占用的空间。VACUUM操作还更新数据库的统计信息,这对于查询优化器来说非常重要。

如果 VACUUM 太慢,则有可能有以下几个原因:

  • 大容量数据:如果数据库非常大,VACUUM操作可能需要很长时间来完成,这会增加系统负载。
  • 高事务量:在高事务量的系统中,频繁的更新、插入和删除操作会产生许多不再需要的行,导致VACUUM工作量增加。
  • 不频繁的清理:如果长时间没有运行VACUUM,会导致数据库中积累大量的死亡行,需要更长时间来清理。

因为当前数据库集群都处于业务的低谷期,所以基本上没有啥负载,所以高事务量 可以排除,而数据库一直在频繁的执行清理任务,所以问题基本上可以锁定到大容量数据!

谁占用了空间?

因此,我们首先从数据表的空间占用上面进行问题排查!

我们可以使用 [[维护相关#数据表统计#数据表空间占用大小 | 数据表空间占用大小统计]] 相关 SQL:

SELECT
relname,
PG_SIZE_PRETTY(PG_TOTAL_RELATION_SIZE(oid)) AS total_size,
PG_SIZE_PRETTY(PG_RELATION_SIZE(oid)) AS relation_size,
*
FROM
pg_class
WHERE
relname LIKE 'pg_%'
AND relname NOT LIKE 'pg_toast_%'
ORDER BY
PG_TOTAL_RELATION_SIZE(oid) DESC
LIMIT 100
;

下面是返回的结果信息:

relname total_size relation_size
pg_attribute 32 GB 23 GB
pg_attribute_relid_attnam_index 5615 MB 5613 MB
pg_class 4303 MB 2877 MB
pg_attribute_relid_attnum_index 3595 MB 3594 MB
pg_depend 3584 MB 1616 MB
pg_type 3030 MB 2092 MB

上面 pg_attribute 总大小(数据表+索引)为:32 GB,因此,基本上可以判断,数据库的负载变高,是由于 pg_attribute 系统表导致的!

pg_attribute

那么问题来了,pg_attribute 到时候是什么数据表呢?

以下是 AI 助手 Kimi 给出的解答:

在PostgreSQL数据库中,pg_attribute是一个系统目录表,它存储了关于表列的信息。每个表的列都有相应的行记录在这个表中,包括系统表和用户定义的表。

pg_attribute表是PostgreSQL中众多系统目录表之一,它们为数据库中的各种对象提供了元数据。通过查询这些系统表,你可以获得关于数据库结构和配置的详细信息。

简而言之,它是一张 pgsql 的元数据信息表,存储 pg 数据库中的各个表字段的定义信息。

理论上,一个数据库中的数据表即使再多,它的元数据信息也不可能超过 30 GB,因此,我们接下来的排查方向,是要找出为什么 pg_attribute 数据表这么大!

数据膨胀

在我将此问题在网络上进行搜索的时候,一个新的名词出现在我的眼前:数据膨胀

PostgreSQL 数据膨胀是指数据库中的数据文件大小超出了实际存储数据所需的大小。这可能会导致存储空间的浪费,并且可能影响数据库的性能。以下是一些可能导致 PostgreSQL 数据膨胀的原因以及相应的解决方法:

  • 索引膨胀

    • 原因:随着数据的更新和删除,索引可能会变得“膨胀”,特别是对于B树索引。
    • 解决方法:定期重建索引可以减少膨胀。可以使用REINDEX命令来实现。
  • 表膨胀
    • 原因:表中的数据更新和删除操作可能导致表变得碎片化,从而增加表的物理大小。
    • 解决方法:使用VACUUM FULL命令来压缩表并回收空间。但请注意,这将创建一个新的表并重置统计信息。
  • 长事务
    • 原因:长时间运行的事务会锁定行,导致VACUUM不能回收空间。
    • 解决方法:避免长时间运行的事务,或者使用事务 ID 来限制事务的持续时间。
  • 未及时清理删除的数据
      • 原因:删除数据后,如果VACUUM没有运行,那么空间不会被回收。
    • 解决方法:定期运行VACUUM(或使用autovacuum)来清理不再需要的行。
  • 系统表膨胀
    • 原因:系统表,如pg_attribute,可能会因为存储了大量的元数据而变得庞大。
    • 解决方法:审查系统表的使用,移除不必要的元数据。

通过对上面造成数据膨胀的原因进行排查,最后锁定了最重要的两条:

  • 重复创建临时表:公司的很多业务涉及到 批量更新 ,为了使批量更新的速度更快,因此使用了 临时表方案 方案,重复执行 CREATE TEMP TABLE AS SELECT * FROM TABLE ,导致 pg_attribute 的数据一直处于上升的阶段。
  • 长事务:数据库的数据需要实时同步至数据仓库,同步是采用的 Flink-CDC 实时同步至 StarRocks,Flink-CDC 在同步阶段,会默认打开一个复制槽,当复制槽的 WAL 日志未被订阅者消费的时候,会存在一个长事务!

问题源头

下面,我来进行一个复盘,来说明为什么 pg_attribute 为什么会发生数据膨胀!

业务系统时时刻刻在执行 CREATE TEMP TABLE 命令,因此 pg_attribute 的数据会频繁的进行数据的插入和删除,正常情况下,及时 PgSql 的 VACUUM 会自动将删除的数据从磁盘中移除。

但是,因为数据库的数据需要同步至 数据仓库 ,因此使用了 Flink-CDC 进行同步,Flink-CDC 会开启一个复制槽,正常运行的情况下, Flink-CDC 会实时消费复制槽中的 WAL 日志,如果 Flink-CDC 同步任务关闭,但是又未关闭复制槽,复制槽为了保证订阅者数据完整性,会自动记录 FLink-CDC 上一次消费的位置,方便 Flink-CDC 下一次重启,重新监听 WAL 日志。

为了保证 WAL 日志的完整性,因此 PgSql 需要开启一个长事务,防止 PgSql 数据库的 VACUUM 把数据从磁盘清除。

所以,pg_attribute 数据表的数据因为长事务的原因,一直未被 VACUUM,所以导致数据表一直处于膨胀阶段,而因为 pg_attribute 是系统表,假如执行 VACUUM FULL pg_attribute ,将会锁全库,因此即使当后续事务关闭了,pg_attribute 的空间也无法得到正常的释放!

解决方案

停止创建临时表

因为系统一直在创建临时表,所以系统一直在对 pg_attribute 表进行 VACUUM ,假如 pg_attribute 的数据不再更新,那么就不会触发数据库的 VACUUM 了!

此方法治标不治本,只是避免了频繁执行 vacuum pg_attribute,从而减小系统负载

执行 VACUUM FULL

执行 vacuum full pg_attribute,但是此方案会锁全库,因此执行的时候,必须停服执行,对业务的影响较大。

PGSQL数据膨胀问题排查的更多相关文章

  1. 以elasticsearch-hadoop 向elasticsearch 导数,丢失数据的问题排查

    实际这是很久之前的问题了,当时没时间记录 这里简单回顾 项目基于 数据架构不方便说太细,最精简的 somedata-> [kafka]->spark-stream->elastics ...

  2. 数据库char varchar nchar nvarchar,编码Unicode,UTF8,GBK等,Sql语句中文前为什么加N(一次线上数据存储乱码排查)

    背景 公司有一个数据处理线,上面的数据经过不同环境处理,然后上线到正式库.其中一个环节需要将数据进行处理然后导入到另外一个库(Sql Server).这个处理的程序是老大用python写的,处理完后进 ...

  3. InnerJoin分页导致的数据重复问题排查

    2016年8月9号美好的七夕的早上,我精神抖擞地来到公司.一会之后,客服宅宅MM微信我,说一个VIP大店铺订单导出报表中一个订单有重复行.于是,我赶紧开始查探问题所在.经过一天的反复仔细追查(当然还包 ...

  4. 【Spark调优】数据倾斜及排查

    [数据倾斜及调优概述] 大数据分布式计算中一个常见的棘手问题——数据倾斜: 在进行shuffle的时候,必须将各个节点上相同的key拉取到某个节点上的一个task来进行处理,比如按照key进行聚合或j ...

  5. Hive数据导入HBase引起数据膨胀引发的思考

    最近朋友公司在做一些数据的迁移,主要是将一些Hive处理之后的热数据导入到HBase中,但是遇到了一个很奇怪的问题:同样的数据到了HBase中,所占空间竟增长了好几倍!详谈中,笔者建议朋友至少从几点原 ...

  6. Mysql 和 Postgresql(PGSQL) 对比

    Mysql 和 Postgresql(PGSQL) 对比 转载自:http://www.oschina.net/question/96003_13994 PostgreSQL与MySQL比较 MySQ ...

  7. Redis性能问题排查解决手册(七)

     阅读目录: 性能相关的数据指标 内存使用率used_memory 命令处理总数total_commands_processed 延迟时间 内存碎片率 回收key 总结 性能相关的数据指标 通过Red ...

  8. Redis性能问题排查解决手册

    转自:http://www.cnblogs.com/mushroom/p/4738170.html 阅读目录: 性能相关的数据指标 内存使用率used_memory 命令处理总数total_comma ...

  9. Spark性能优化之道——解决Spark数据倾斜(Data Skew)的N种姿势

    原创文章,同步首发自作者个人博客转载请务必在文章开头处注明出处. 摘要 本文结合实例详细阐明了Spark数据倾斜的几种场景以及对应的解决方案,包括避免数据源倾斜,调整并行度,使用自定义Partitio ...

  10. 干货!一次kafka卡顿事故排查过程

    由于一次功能上线后,导致某数据量急剧下滑,给我们紧张的呢!排查过程也是个学习过程(这其中有大部分是领导们的功劳,不过分享给大家应该也不犯法吧,ᐓ) 1. 确认问题的真实性? 被数据部门告知,某数据量下 ...

随机推荐

  1. TVM:使用张量表达式处理算子

    在本教程中,把注意力转向 TVM 如何使用张量表达式(Tensor Expression,简称 TE)定义张量计算并应用循环优化.TE 以纯函数式语言描述张量计算(即每个表达式都没有副作用).从 TV ...

  2. C# 之静态构造器与静态字段初始化器

    public class Test { /// <summary> /// 静态字段初始化器会在调用静态构造器前运行. /// 如果类型没有静态构造器,字段会在类型被使用前或运行时中更早的 ...

  3. No grammar constraints (DTD or XML schema) detected for the document

    warning: No grammar constraints (DTD or XML schema) detected for the document 未检测到文档的语法约束(DTD或XML模式) ...

  4. manim变换效果总结

    在ManimCE中,除了上一篇介绍的丰富的动画效果外,变换效果也是制作精彩视觉内容的重要工具. 变换效果主要用于改变对象的形状.大小.颜色或位置,让对象在动画中呈现出动态的变化. 本文详细总结了 Ma ...

  5. excel/wps, 转code128字体宏, 部分字符串出现空格, 导致条码断裂无法扫描的解决方案

    原宏是网上抄的, 传播比较广的那个. 后来发现, 部分条码出现空格断裂, 导致PDA无法扫描, 经搜索在一个帖子里, 发现是因为: 宏计算条码时, 会出现校验位刚好是空格的情况, 而空格在code12 ...

  6. 乌班图20.04上安装java配置tomcat9

    原文参考:https://blog.csdn.net/u010763324/article/details/122678528 Apache Tomcat是一个开源的 Web 服务器和 Java se ...

  7. 2025年KOL运营工具深度测评:11款高效工具全面解析,助力品牌全流程管理

    在数字营销日益精精化的今天,KOL(关键意见领袖)已成为品牌传播和用户转化的重要力量.然而,面对多平台.多任务的复杂协作需求,如何高效管理KOL资源.优化合作流程.提升ROI,成为品牌促销经理们急需解 ...

  8. 安全感知平台SIP-部署简介

    部署安装前前期调研: NDR:全流量高级威胁检测: NDR是一款专门围绕"高级威胁检测"为核心,主打全流量采集.快速检测.威胁定位.研判溯源.联动闭环一体化的专业流量检测系统:内置 ...

  9. 深入探讨控制反转(IOC)与依赖注入(DI)模式原理与应用实践

    本文由 ChatMoney团队出品 在软件开发中,控制反转(Inversion of Control,简称IOC)和依赖注入(Dependency Injection,简称DI)是两种常用的设计模式, ...

  10. PHP中关于static的使用方法

    本文由 ChatMoney团队出品 PHP,作为一种面向对象的编程语言,为开发者提供了丰富的特性和功能,助力构建高效的应用程序.其中,static关键字在类和方法中的应用尤为重要,它提供了一种独特的变 ...