1 Vacuum 概念
Vacuum 是PG 为了实现MVCC(多版本并发控制)而采用的一种技术。 不同数据库实现MVCC 方法不一样。
1.1 Oracle/MySQL
这两种数据库是通过undo日志来实现MVCC。当数据记录被DML修改,将修改前的数据记录在undo log中,客户端可以读取数据时,通过undo log指针进行回滚找到对应可见的版本。
长事物、大事物会导致undo log暴涨,一定程度上会导致系统日志文件磁盘空间占用的暴涨。只有将事物提交/回滚,相关版本记录不再需要时,对应的版本数据才会被清理,undo系统文件空间才会把无效的版本空间进行释放。
1.2 SQL Server
它是通过tempdb数据库来实现的。当数据记录被DML修改,将旧版本数据写入tempdb进行存储,客户端读取数据时,可从通过指针找到tempdb数据库中对应可见的版本。
长事物、大事物会导致tempdb空间暴涨,只有事物提交,相关版本记录不再需要时,才会将相关的版本记录进行释放,需要注意的是这部分磁盘空间消耗是没有释放给操作系统的,需要手动进行磁盘空间收缩。
1.3 PostgreSQL
通过保留变更前的记录来实现MVCC的。当数据记录被DML修改,旧版本记录仍保留不变,仅仅需要修改相关记录的xmin、xmax属性,并新增写入变更后的版本记录数据。
由于历史版本数据仍然保留在原表空间中,默认情况下autovacuum会按照一定的参数设置策略检测并进行一定的清理,但频繁的数据变极大可能导致旧版本数据空间来不及进行空间回收,从而导致表空间膨胀。
1.4 MVCC实现方法对比
通过undo log或者tempdb来进行旧版本存储的方式,有效的避免了表空间膨胀,相对于PG直接保留旧版本数据的方式,每次DML操作都需要额外的日志写入,存在一定的IO消耗(目前SSD盘存储下,感觉影响不会很大);
PG这种直接保留旧版本数据的方式,无需额外的日志写入的消耗,但是一定程度上会导致旧版本数据没有及时清理,导致表空间膨胀,影响该表数据的查询效率(扫描了不必要的数据页)。
2 AutoVacuum 配置
2.1 AutoVacuum 参数
autovacuum为PG数据库中可以实现自动vacuum的一个守护进程(postgres: autovacuum launcher),需要数据库将参数autovacuum参数打开。
autovacuum会自动检测发生了大量DML操作的表对象,并对其进行垃圾回收和统计信息的重新采集,相当于手动执行 vacuum analyze 。
[root@dave ~]# ps -ef|grep postgre
postgres 112702 1 0 20:44 ? 00:00:00 /usr/pgsql-14/bin/postgres -D /data/postgresql/data14
postgres 112703 112702 0 20:44 ? 00:00:00 postgres: logger
postgres 112705 112702 0 20:44 ? 00:00:00 postgres: checkpointer
postgres 112706 112702 0 20:44 ? 00:00:00 postgres: background writer
postgres 112707 112702 0 20:44 ? 00:00:00 postgres: walwriter
postgres 112708 112702 0 20:44 ? 00:00:00 postgres: autovacuum launcher
postgres 112709 112702 0 20:44 ? 00:00:00 postgres: stats collector
postgres 112710 112702 0 20:44 ? 00:00:00 postgres: logical replication launcher
root 123251 122926 0 21:10 pts/4 00:00:00 vim postgresql.conf
root 127476 127335 0 21:20 pts/6 00:00:00 grep --color=auto postgre
[root@dave ~]#
在PG的配置文件中,有一部分是AutoVacuum的配置。
#------------------------------------------------------------------------------
# AUTOVACUUM
#------------------------------------------------------------------------------
#autovacuum = on # Enable autovacuum subprocess? 'on'
# requires track_counts to also be on.
#autovacuum_max_workers = 3 # max number of autovacuum subprocesses
# (change requires restart)
#autovacuum_naptime = 1min # time between autovacuum runs
#autovacuum_vacuum_threshold = 50 # min number of row updates before
# vacuum
#autovacuum_vacuum_insert_threshold = 1000 # min number of row inserts
# before vacuum; -1 disables insert
# vacuums
#autovacuum_analyze_threshold = 50 # min number of row updates before
# analyze
#autovacuum_vacuum_scale_factor = 0.2 # fraction of table size before vacuum
#autovacuum_vacuum_insert_scale_factor = 0.2 # fraction of inserts over table
# size before insert vacuum
#autovacuum_analyze_scale_factor = 0.1 # fraction of table size before analyze
#autovacuum_freeze_max_age = 200000000 # maximum XID age before forced vacuum
# (change requires restart)
#autovacuum_multixact_freeze_max_age = 400000000 # maximum multixact age
# before forced vacuum
# (change requires restart)
#autovacuum_vacuum_cost_delay = 2ms # default vacuum cost delay for
# autovacuum, in milliseconds;
# -1 means use vacuum_cost_delay
#autovacuum_vacuum_cost_limit = -1 # default vacuum cost limit for
# autovacuum, -1 means use
# vacuum_cost_limit
参数说明
1.autovacuum : 是否开启autovacuum守护进程,默认开启
2.log_autovacuum_min_duration : 指定autovacuum执行耗时超过该参数时,将对应操作记录到日志,-1表示禁用autovacuum的日志记录
3.autovacuum_max_workers : autovacuum可启动的最大worker数,默认为3
4.autovacuum_naptime : 指定两次autovacuum之间的时间延迟,默认为1min
5.autovacuum_vacuum_threshold 、autovacuum_vacuum_scale_factor : 指定一张表Delete、Update的tuple数超过 autovacuum_vacuum_scale_factor * table_size + autovacuum_vacuum_threshold 时,自动触发autovacuum。默认autovacuum_vacuum_threshold为50,autovacuum_vacuum_scale_factor为20
6.autovacuum_vacuum_insert_threshold 、 autovacuum_vacuum_insert_scale_factor : 指定一张表Insert的tuple数超过 autovacuum_vacuum_insert_scale_factor * table_size + autovacuum_vacuum_insert_threshold 时,自动触发autovacuum。默认autovacuum_vacuum_insert_threshold为50,autovacuum_vacuum_insert_scale_factor为20
7.autovacuum_analyze_threshold 、autovacuum_analyze_scale_factor : 指定一张表Insert、Delete、Update的tuple数超过 autovacuum_analyze_scale_factor * table_size + autovacuum_analyze_threshold 时,自动触发analyza操作。默认autovacuum_analyze_threshold为50,autovacuum_analyze_scale_factor为20
8.autovacuum_freeze_max_age : 为防止表中事物ID回卷,指定表的最大事物ID(pg_class.relfrozenxid),超过该参数值自动触发autovacuum,即使autovacuum参数设置为off
9.autovacuum_multixact_freeze_max_age : 为防止表中多个事物ID回卷,指定表的最大事物ID(pg_class.relminmxid),超过该参数值自动触发autovacuum,即使autovacuum参数设置为off
10.autovacuum_vacuum_cost_delay : 指定计算autovacuum的代价延迟值
11.autovacuum_vacuum_cost_limit : 指定autovacuum操作的代价限制值
2.2 AutoVacuum 工作原理
根据参数的配置,autovacuum 相关规则如下:
1.当参数autovacuum设置为on时,数据库会启动一个autovacuum的守护进程,当满足触发条件时启动相关的autovacuum经常进行垃圾回收操作;
2.当表update,delete的tuples数量超过 autovacuum_vacuum_scale_factor * table_size + autovacuum_vacuum_threshold 时,自动触发autovacuum操作
3.当表insert的tuples数量超过 autovacuum_vacuum_insert_scale_factor * table_size + autovacuum_vacuum_insert_threshold 时,自动触发autovacuum操作
4.当表的insert,delete,update的tuple超过 autovacuum_analyze_scale_factor * table_size + autovacuum_analyze_threshold 时,自动触发analyza操作
5.当表的最大事物ID超过autovacuum_freeze_max_age、autovacuum_multixact_freeze_max_age 时,自动触发autovacuum操作
6.默认两次autovacuum之前的时间间隔为autovacuum_naptime,且每次进行autovacuum时可启动的最大并发数为autovacuum_max_workers
2.3 AutoVacuum 配置
全局参数并不一定适用于所有表,特殊表可在表级别定义相关参数。例如变更频繁的表,可适当减少autovacuum_vacuum_scale_factor、autovacuum_vacuum_threshold参数值,使得其可以及时的垃圾回收,避免表膨胀影响其查询效率。
autovacuum_max_workers可根据操作系统CPU资源进行适当调整。
3 手工执行Vacuum
除了上面说的autovacuum之外,也可以手工执行。
语法如下:
VACUUM [ ( option [, ...] ) ] [ table_and_columns [, ...] ]
VACUUM [ FULL ] [ FREEZE ] [ VERBOSE ] [ ANALYZE ] [ table_and_columns [, ...] ]
where option can be one of:
FULL [ boolean ]
FREEZE [ boolean ]
VERBOSE [ boolean ]
ANALYZE [ boolean ]
DISABLE_PAGE_SKIPPING [ boolean ]
SKIP_LOCKED [ boolean ]
INDEX_CLEANUP { AUTO | ON | OFF }
PROCESS_TOAST [ boolean ]
TRUNCATE [ boolean ]
PARALLEL integer
and table_and_columns is:
table_name [ ( column_name [, ...] ) ]
参数说明:
VACUUM FULL
执行期间需要获取对应表的独占锁,阻塞其他客户端的读写操作。该模式下会将对应表数据重新写入一个新的表空间文件,最后替换为新的表文件,这种方式下可以回收dead tuple空间并释放给操作系统。该操作执行消耗是比较大的,且耗时的。
VACUUM FREEZE
使用一种激进的方式冻结元祖,相当于把参数 vacuum_freeze_min_age 、 vacuum_freeze_table_age 设置为0。该模式下Full参数指定是多余的,该操作执行消耗同样是比较大的,且耗时的。
VACUUM VERBOSE
执行期间不需要获取对应表的独占锁,允许其他客户端的并发读写操作。该模式下仅仅会将dead tuple空间进行回收并释放给数据库,并不会释放给操作系统,vacuum期间打印每张表详细的垃圾回收记录。
VACUUM ANALYZE
执行期间不需要获取对应表的独占锁,允许其他客户端的并发读写操作,执行完毕vacuum后会再次执行analyza重新采集相关表的统计信息。该模式下仅仅会将dead tuple空间进行回收并释放给数据库,并不会释放给操作系统。
VACUUM INDEX_CLEANUP ON
默认情况下,vacuum会跳过index vacuum, 当INDEX_CLEANUP 设置为ON时,vacuum 在释放表和索引的dead tuple。
更多参数说明参考官方手册:
使用示例:
[dave@www.cndba.cn data14]# su - postgres
Last login: Sat Dec 17 16:31:55 CST 2022 on pts/3
-bash-4.2$ psql
psql (14.6)
Type "help" for help.
postgres=# /c cndba
You are now connected to database "cndba" as user "postgres".
cndba=# vacuum (analyze,verbose,index_cleanup on) dave;
INFO: vacuuming "public.dave"
INFO: table "dave": found 0 removable, 1 nonremovable row versions in 1 out of 1 pages
DETAIL: 0 dead row versions cannot be removed yet, oldest xmin: 872
Skipped 0 pages due to buffer pins, 0 frozen pages.
CPU: user: 0.00 s, system: 0.00 s, elapsed: 0.00 s.
INFO: analyzing "public.dave"
INFO: "dave": scanned 1 of 1 pages, containing 1 live rows and 0 dead rows; 1 rows in sample, 1 estimated total rows
VACUUM
cndba=#
版权声明:本文为博主原创文章,未经博主允许不得转载。