首页 > 数据库 >PGSQL数据膨胀问题排查

PGSQL数据膨胀问题排查

时间:2024-07-12 11:12:17浏览次数:15  
标签:数据表 attribute 数据库 PGSQL 排查 pg VACUUM 膨胀 数据

背景

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

1715823287451.png

并且占用较高的 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,但是此方案会锁全库,因此执行的时候,必须停服执行,对业务的影响较大。

标签:数据表,attribute,数据库,PGSQL,排查,pg,VACUUM,膨胀,数据
From: https://www.cnblogs.com/booleandev/p/18297867/pgsql-data-expansion-problem-investigation-1

相关文章

  • ECS 宝塔安装PGSQL, pgvector整合的一次记录
    前提安装宝塔面板准备好pgvector ESC>su-upostgres>psql//新建一个用户createuseraideepinwithpassword'123456';//新建一个数据库createdatabaseaideepinowneraideepin;//查看用户SELECTrolname,rolpasswordFROMpg_authid;//修改用户密码......
  • Etcd 故障排查
    Etcd磁盘空间爆满解决方案etcd默认的空间配额限制为2G,超出空间配额限制就会影响服务,所以需要定期清理设置环境变量ETCD_CA_CERT="/etc/kubernetes/pki/etcd/ca.crt"ETCD_CERT="/etc/kubernetes/pki/etcd/server.crt"ETCD_KEY="/etc/kubernetes/pki/etcd/server.key"HOST......
  • Linux环境中应急响应与排查溯源思路总结
    0前言在应急响应和溯源时,经常会遇见Linux系统环境,然后小编经常只记得思路忘记部分命令,下面是小编对Linux环境下应急响应和排查的思路总结。本文来源无问社区(wwlib.cn)更多详细内容可前往观看http://www.wwlib.cn/index.php/artread/artid/2729.html1目录文件分析1.1系统用......
  • TNS问题排查 The listener supports no services
     检查tns的日志信息查看具体报错详情/u01/app/oracle/diag/tnslsnr/<hostname>/listener/alert/log.xml 修改litener.ora #listener.oraNetworkConfigurationFile:/u01/app/oracle/product/11.2.0/dbhome_1/network/admin/listener.ora#GeneratedbyOracleco......
  • windows基线排查与安全加固
    什么是安全基线安全基线是为了实现基本防护需求而制定的一系列基准,通过对系统生命周期不同阶段的安全检查,建立良好的安全配置项和安全措施,通过分析安全状态的变化趋势控制安全风险。在建立事件响应机制之前,必须存在基础的能力。这些基础能力用于保障数字资产/业务的可用性、保密......
  • Pgsql帮助类 netcore
    十年河东,十年河西,莫欺少年穷学无止境。精益求精usingNpgsql;usingSystem;usingNpgsqlTypes;usingSystem.Data;usingSystem.Collections.Generic;usingSystem.Reflection;usingSystem.Configuration;usingswapCommon;namespacePgSqlHelper{publiccla......
  • 线上的一次fullgc排查过程
    线上服务的GC问题,是Java程序非常典型的一类问题,非常考验工程师排查问题的能力。同时,几乎是面试必考题,但是能真正答好此题的人并不多,要么原理没吃透,要么缺乏实战经验。 过去半年时间里,我们的广告系统出现了多次和GC相关的线上问题,有FullGC过于频繁的,有YoungGC耗时过长的,这些问......
  • Spring Boot 中 PGSQL 判断打卡点是否经过轨迹优化代码,循环查询物理表修改生成临时表,
    记录一下一个业务问题,流程是这样的,我现在有一个定时任务,5分钟执行一次,更新车辆打卡的情况。现在有20俩车,每辆车都分配了路线,每条路线都有打卡点,每个打卡点分配了不同的时间段,也就是说,一条路线可能有几百个打卡点,这几百个打卡点中每一个都分配了时间段,有可能是1个时间段,比如8......
  • 在开发环境中使用 RawCap 和 Wireshark 排查本地回路地址
    如何使用RawCap和Wireshark排查本地网络请求中的404错误开发微服务应用时,正确配置网络请求的转发至关重要。本文将通过一个具体示例来展示如何使用RawCap和Wireshark来监控和分析本地回路请求,并排查导致HTTP404错误的可能原因。背景在本例中,用户的浏览器请求经过多......
  • 使用grafana loki dashboard排查系统间mq消息问题
    背景:几个系统间通过rocketmq的消息传递信息,用户反馈该功能存在一些数据不一致,应该是mq消息丢失或者系统在发消息时候报错,因此在代码中先打上日志并发布。日志由多个[tag]加详细信息组成,例子如:log.info("[MqAction][Proxy][ProxyMqReceive][ProxyNotificationCnsmRouteMqReceive]......