PostgreSQL 难搞的事系列 --- vacuum 的由来与PG16的命令的改进 (1)

news2024/11/19 16:40:26

130e94df5176e71df3ebf4f39367e4c6.png

开头还是介绍一下群,如果感兴趣PolarDB ,MongoDB ,MySQL ,PostgreSQL ,Redis, Oceanbase, Sql Server等有问题,有需求都可以加群群内有各大数据库行业大咖,CTO,可以解决你的问题。加群请联系 liuaustin3 ,在新加的朋友会分到2群(共1720人左右 1 + 2 + 3 + 4+5) 另欢迎 OpenGauss GAUSSDB的技术人员加入

PostgreSQL 的内容之前写上百篇,这里打算开一个系列,叫PostgreSQL难搞的事情,主要针对PostgreSQL中经常被问及的问题和一些导致这些问题深层次的原因的一个主题。这次的主题从PostgreSQL的vacuum 开始,

说到Vacuum 属于是几家欢喜几家愁的,一般发愁的都是那些PostgreSQL 业务繁忙的大库,并且经常出现业务高峰期的一些系统性能的波动。但大部分人都只关注Vacuum, autovacuum 而忽略了一些为什么会产生这样动作的原因,同时不少人对 aggressive vacuum 的是什么不了解,导致vacuum 和  aggressive vacuum 的问题搞不清,最终导致严重的问题。

首先vacuum 的由来这个问题需要反复的说,在我们进行多版本控制,MVCC multiversion concurrency control ,是产生PG vacuum的根源 mvcc主要目的就是提供在数据库访问中可以进行并发访问,并发访问则需要对于事务中的数据提供同一行数据,在不同时间中访问中的版本信息,而这些信息是集中式,还是分散式是两种数据库设计的不同。

在PostgreSQL中我们使用了分散式,也就是将所有的行的版本信息驻留在我们的数据表内,基于这样的处理方式,导致后续这些失效的版本行信息需要进行清理,而清理这些行的信息的过程称为vacuum,相对应的我们会有 vacuum 和 autovacuum的命令和相关的过程来进行相关的工作,而基于这样的形成方式,导致PostgreSQL 应对这部分工作并产生了一套与其他数据库截然相反的工作。

在工作中我们大概率会遇到以下的一些问题

1  回收不及时,触发数据库回卷,导致触发aggresive vaccum,或最终导致freezing boom 触发单用户模式。

2  触发Autovacuum进行回收与系统正在进行高耗能操作撞车,导致系统性能出现瓶颈影响正常业务

3  关于vacuum的命令和参数多每个版本都有新的东西的加入,变化多部分版本对于命令参数进行了改变,并且参数的细致程度高,大部分人无法进行有效配置和调配

所以基于这些问题,我们需要分几期来说这个问题,整体系统化的梳理,基于数据库设计产生的一些在PostgreSQL中的特殊的需求的问题。

本期是这个系列的第一篇,所以我们先从问题的起源来详细说一说,这里我们看下图,下面两个图清晰的展示了数据表中某行的数据产生新一个行版本和老版本行共存的过程,以及访问中通过老的行指向新的行的过程等。

ad5e7456aad516336a92e60b3ed4172a.png

0766fffc592f1f2ad5e6edd585275934.png

必然在上一个版本的行在所有事务中都成为历史行后,会成为死行,死行就相当于其他数据库中UNDO 中需要被清理的数据信息。

基于MVCC的形成,PostgreSQL的每行上都会对于他是那个数据库库事务的归属进行标记,在这样的情况下,标记每行属于那个事务的数字,txid也有使用耗费光的情况,基于这个数字的大小为2的32次方,那么在回收这些txid 号的情况下,很有可能由于一些情况而无法对这些txid的号进行收回,而长时间无法收回这些txid的情况就会导致数据库产生 aggressive vacuum ,aggressive vaccum 。

导致aggressive vacuum 后最大的问题是,aggressive vacuum中的扫描工作,普通的vacuum本身并不会对数据表中每页的数据进行扫描,而aggressive vacuum 则是针对未冻结的数据页面全部扫描,扫描中会导致大表较长时间在进行整体的页面扫描,扫描期间的CPU 和IO 均会为此项工作服务,同时还会导致长时间针对这张表无法进行DDL操作。所以我们在工作中,都在尽力的避免发生  aggressive vacuum 的工作。

下面我们通过一个列子来进行展示,我们找到一张表,其中我们计算出他的相关的age 是 478

postgres=# SELECT c.oid::regclass as table_name,greatest(age(c.relfrozenxid),age(t.relfrozenxid)) as age                                                                                                                                                    
postgres-# FROM pg_class c                                                                           
postgres-# LEFT JOIN pg_class t ON c.reltoastrelid = t.oid
postgres-# WHERE c.relkind IN ('r', 'm') and c.oid::regclass::varchar = 'time_test';
 table_name | age 
------------+-----
 time_test  | 478
(1 row)


然后我们针对这张表进行vacuum 的操作,然后我们在观察相关的这张表的age

postgres=# vacuum verbose time_test;
INFO:  vacuuming "public.time_test"
INFO:  table "time_test": found 0 removable, 1 nonremovable row versions in 1 out of 1 pages
DETAIL:  0 dead row versions cannot be removed yet, oldest xmin: 878875
0 pages removed.
Skipped 0 pages due to buffer pins, 0 frozen pages.
CPU: user: 0.00 s, system: 0.00 s, elapsed: 0.00 s.
VACUUM
postgres=#

在我们对表进行vacuum后,发现表的age还是 478,并未有任何的变化。在我们改变命令后,针对这个表进行freeze 的操作后,我们在观察age的部分已经变为0.

77e30f311630bd3977eaaa267513d47a.png

postgres=# vacuum freeze verbose  time_test;
INFO:  aggressively vacuuming "public.time_test"
INFO:  table "time_test": found 0 removable, 1 nonremovable row versions in 1 out of 1 pages
DETAIL:  0 dead row versions cannot be removed yet, oldest xmin: 878875
0 pages removed.
Skipped 0 pages due to buffer pins, 0 frozen pages.
CPU: user: 0.00 s, system: 0.00 s, elapsed: 0.00 s.
VACUUM
postgres=# SELECT c.oid::regclass as table_name,greatest(age(c.relfrozenxid),age(t.relfrozenxid)) as age                                                                                                                                                    
FROM pg_class c                                                                           
LEFT JOIN pg_class t ON c.reltoastrelid = t.oid
WHERE c.relkind IN ('r', 'm') and c.oid::regclass::varchar = 'time_test';
 table_name | age 
------------+-----
 time_test  |   0
(1 row)

d4017ab1467ab9c4a8e64c32417b8f6e.png

postgres=# SELECT
postgres-# oid::regclass::text AS table,
postgres-# age(relfrozenxid) AS xid_age,
postgres-# mxid_age(relminmxid) AS mxid_age,
postgres-# least(
postgres(# (SELECT setting::int
postgres(# FROM pg_settings
postgres(# WHERE name = 'autovacuum_freeze_max_age') - age(relfrozenxid),
postgres(# (SELECT setting::int
postgres(# FROM pg_settings
postgres(# WHERE name = 'autovacuum_multixact_freeze_max_age') - mxid_age(relminmxid)
postgres(# ) AS tx_before_wraparound_vacuum,
postgres-# pg_size_pretty(pg_total_relation_size(oid)) AS size,
postgres-# pg_stat_get_last_autovacuum_time(oid) AS last_autovacuum
postgres-# FROM pg_class
postgres-# WHERE not (relfrozenxid = 0)
postgres-# AND oid > 16384
postgres-# ORDER BY tx_before_wraparound_vacuum;
        table         | xid_age | mxid_age | tx_before_wraparound_vacuum |    size    | last_aut
----------------------+---------+----------+-----------------------------+------------+---------
 test_t               |     289 |        0 |                   199999711 | 127 MB     | 
 collates             |     253 |        0 |                   199999747 | 56 kB      | 
 test_table           |     234 |        0 |                   199999766 | 40 kB      | 
 xcc.xcc              |     210 |        0 |                   199999790 | 0 bytes    | 
 pgbench_history      |      14 |        0 |                   199999986 | 0 bytes    | 
 pgbench_accounts     |      14 |        0 |                   199999986 | 13 GB      | 
 pgbench_branches     |      14 |        0 |                   199999986 | 112 kB     | 
 pgbench_tellers      |      14 |        0 |                   199999986 | 712 kB     | 
 bank                 |       3 |        0 |                   199999997 | 40 kB      | 
 dba_autovacuum_table |       0 |        0 |                   200000000 | 8192 bytes | 
 time_test            |       0 |        0 |                   200000000 | 56 kB      | 
(11 rows)

上面的脚本可以方便的查看当前的数据库中表中的AGE 以及发生回卷的计数器的数值。

在PostgreSQL 16 中针对vaccumdb 命令有了一些变化,我们把PG14 和PG16 的vacuumdb 

7c0b6611b1b0d70fc53078eab59705e8.png

我们清晰的看到有四个部分是不同的

1 --buffer-usage-limit=SIZE

2   --no-process-main 

3   -n, --schema=PATTERN 

4   -N, --exclude-schema=PATTERN

具体上我们可以对1 ,2 两个部分进行更细的研究

buffer-usage-limit 命令主要的意义,主要的目的还是针对具有大内存的主机,在进行vaccum的过程中,可以给与更多的内存,尽量对于大表进行快速有效的vacuum。相关范围在不开启和 128KB - 16G 之间进行设置。

7fcdb2be1684a76ff002c3c40aab6216.png

3c12851bf8f05e11543c87c24b6d7773.png

--no-process-main 这个主要添加的参数是为了不进行表的vacuum 只对表中的toast进行vacuum。

1ed3d1a18d4a882e431f868a554cf11e.png

参考:https://www.postgresql.org/message-id/08930c0b541700a5264e5fbf3a685f5a@oss.nttdata.com

064f6345b201ef8e391de1fe161d8191.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1225893.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

《向量数据库指南》——什么是 向量数据库Milvus Cloud的Range Search?

Range Search 功能诞生于社区。 某天,一位做系统推荐的用户在社区提出了需求,希望 Milvus Cloud 能提供一个新功能,可以返回向量距离在一定范围之内的结果。而这不是个例,开发者在做相似性查询时,经常需要对结果做二次过滤。 为了帮助用户解决这一问题,Milvus Cl…

redis安装(Windows和linux)

如何实现Redis安装与使用的详细教程 Redis 简介 Redis是一个使用C语言编写的开源、高性能、非关系型的键值对存储数据库。它支持多种数据结构,包括字符串、列表、集合、有序集合、哈希表等。Redis的内存操作能力极强,其读写性能非常优秀,且…

英飞凌(Infineon)平台嵌入式开发基础

本篇文章介绍了基于英飞凌平台进行嵌入式开发的一些基础知识,首先介绍了涉及芯片的信息和常见的开发环境,把生硬的主体名称先分类并抛出来;然后着重介绍了英飞凌官网提供的开发资源,包括不限于开发环境,代码示例&#…

Spring学习②__IOC分析

目录 IOC控制反转IOCIOC理论案例IOC的思想(注入)IOC底层什么是 IOCIOC 底层原理 总结 IOC 控制反转IOC ①控制反转,把对象创建和对象之间的调用过程,交给Spring进行 ②使用IOC目的:为了耦合度降低 IOC理论案例 控制…

深度学习中对抗生成网络GAN背后的数学原理

引言 GAN的风暴席卷了整个深度学习圈子,任何任务似乎套上GAN的壳子,立马就变得高大上了起来。那么,GAN究竟是什么呢? GAN的主要应用目标: 生成式任务(生成、重建、超分辨率、风格迁移、补全、上采样等&a…

判断序列值是否单调递增 PandasSeries中的方法:is_monotonic_increasing

【小白从小学Python、C、Java】 【计算机等考500强证书考研】 【Python-数据分析】 判断序列值是否单调递增 PandasSeries中的方法: is_monotonic_increasing 选择题 请问下列程序运行的的结果是: import pandas as pd s1 pd.Series([1, 2, 5]) prin…

linux如何使用Xshell远程连接

简介:本文的一切条件基于redhat的linux操作系统。 1、创建虚拟机: 如有需要,请转至【linux基础】在VMware上安装RHEL9详细教程_融社的博客-CSDN博客 (如若侵权,该篇立删) 2、使用命令查看网段信息 打…

ThreadLocal优化

测试类证明一下ThreadLocal存储的数据是线程程安全的 package com.lin.springboot01;import org.junit.jupiter.api.Test;public class testThreadLocal {Testpublic void testThreadLocalSetAndGet(){//提供一个ThreadLocal对象ThreadLocal t1 new ThreadLocal();new Thread…

复旦大学EMBA深度链接深圳科创产业:聚焦智联,产融未来

作为科创成就的经济大区,深圳南山区通过跨界创新研发生态链条,领跑科创产业创新,以187.5平方公里的面积,雄踞着204家上市公司,地均生产总值产出达到了40.7亿元,相当于每平方公里出产超过1家上市公司&#x…

openwrt配置ipv6

废话部分(可跳过) 历经多天,经过各种测试,终于把openwrt的ipv6配置成功了,这篇我将尽我所能详尽的描述一下可能遇到的问题和解决办法。这篇文章致力于让你完成整个openwrt的ipv6配置,希望对你有所帮助。在…

sentinel 网关

网关简介 大家都都知道在微服务架构中,一个系统会被拆分为很多个微服务。那么作为客户端要如何去调用这么多的微服务呢?如果没有网关的存在,我们只能在客户端记录每个微服务的地址,然后分别去调用。 这样的架构,会存在…

WinForms C# 导入和导出 CSV 文件 Spread.NET

使用 WinForms C# 和 VB.NET 导入和导出 CSV 文件 2023 年 11 月 17 日 使用 Spread.NET 直接在 .NET WinForms 应用程序中处理 CSV 文件。 Spread.NET可帮助您创建电子表格、网格、仪表板和表单。它包括一个强大的计算引擎,具有 450 多个函数以及导入和导出 Micros…

Django的可重用HTML模板示例

01-配置并运行Django项目 首先按照博文 https://blog.csdn.net/wenhao_ir/article/details/131166889配置并运行Django项目。 02-创建可重用模板文件 templates目录下新建目录common,然后在目录common下新建文件:navbar.html,并写入下面的…

火山引擎 ByteHouse 的增强型数据导入技术实践

作为企业数字化建设的必备要素,易用的数据引擎能帮助企业提升数据使用效率,更好提升数据应用价值,夯实数字化建设基础。 数据导入是衡量OLAP引擎性能及易用性的重要标准之一,高效的数据导入能力能够加速数据实时处理和分析的效率。…

【LLM】基于LLM的agent应用(更新中)

note 在未来,Agent 还会具备更多的可扩展的空间。 就 Observation 而言,Agent 可以从通过文本输入来观察来理解世界到听觉和视觉的集成;就 Action 而言,Agent 在具身智能的应用场景下,对各种器械进行驱动和操作。 Age…

maptalks三维地图网址

三维 地址: http://examples.maptalks.com/examples/cn/gltf/gltf-marker/shader

【漏洞复现】浙大恩特CRM文件上传0day

漏洞描述 浙大恩特客户资源管理系统任意文件上传漏洞 免责声明 技术文章仅供参考,任何个人和组织使用网络应当遵守宪法法律,遵守公共秩序,尊重社会公德,不得利用网络从事危害国家安全、荣誉和利益,未经授权请勿利用文章中的技术资料对任何计算机系统进行入侵操作。利用…

表白墙/留言墙 —— 中级SpringBoot项目,MyBatis技术栈MySQL数据库开发,练手项目前后端开发(带完整源码) 全方位全步骤手把手教学

🧸欢迎来到dream_ready的博客,📜相信你对这篇博客也感兴趣o (ˉ▽ˉ;) 📜表白墙/留言墙初级Spring Boot项目(此篇博客的简略版,不带MyBatis数据库开发) 目录 1、项目前端页面及项目…

C/C++ 运用WMI接口查询系统信息

Windows Management Instrumentation(WMI)是一种用于管理和监视Windows操作系统的框架。它为开发人员、系统管理员和自动化工具提供了一种标准的接口,通过这个接口,可以获取有关计算机系统硬件、操作系统和应用程序的信息&#xf…

nodejs微信小程序-利康药房管理系统的设计与实现- 安卓-python-PHP-计算机毕业设计

目 录 摘 要 I ABSTRACT II 目 录 II 第1章 绪论 1 1.1背景及意义 1 1.2 国内外研究概况 1 1.3 研究的内容 1 第2章 相关技术 3 2.1 nodejs简介 4 2.2 express框架介绍 6 2.4 MySQL数据库 4 第3章 系统分析 5 3.1 需求分析 5 3.2 系统可行性分析 5 3.2.1技术可行性:…