PostgreSQL vacuum_freeze_table_age和vacuum_freeze_min_age理解

本文深入解析了PostgreSQL中vacuum_freeze_min_age参数的作用,通过设置此参数,用户可以自定义在执行VACUUM操作时冻结行版本的最小事务年龄,从而实现对数据库表的定期自动清理。通过插入测试数据、手动设置参数值、执行VACUUM操作并观察结果,本文展示了如何利用此参数优化数据库性能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  • **vacuum_freeze_table_age : ** 当表的pg_class.relfrozenxid域达到该设置指定的年龄时,VACUUM会执行一次全表扫描。默认值是 1.5 亿个事务。尽管用户可以把这个值设置为从 0 到 20 亿,VACUUM会悄悄地将有效值设置为autovacuum_freeze_max_age值的95%,因此在表上启动一次反回卷自动清理之前有机会进行一次定期手动VACUUM。

  • **vacuum_freeze_min_age : ** 指定VACUUM在扫描表时用来决定是否冻结行版本的切断年龄(以事务计)。默认值是 5 千万个事务。尽管用户可以将这个值设置为从 0 到 10 亿,VACUUM会悄悄地将有效值设置为autovacuum_freeze_max_age值的一半,这样在强制执行的自动清理之间不会有过短的时间间隔。。

理解vacuum_freeze_min_age参数:

1. 插入测试数据

postgres=# insert into tb9 select generate_series(1,5),'aa';
INSERT 0 5

postgres=# select xmin,age(xmin),xmax,* from tb9;
 xmin | age | xmax | id | name 
------+-----+------+----+------
 2523 |   1 |    0 |  1 | aa
 2523 |   1 |    0 |  2 | aa
 2523 |   1 |    0 |  3 | aa
 2523 |   1 |    0 |  4 | aa
 2523 |   1 |    0 |  5 | aa
(5 rows)

2. 手动设置vacuum_freeze_min_age 值

postgres=# set vacuum_freeze_min_age =10;
SET

  这个设置为10的意思是当age(xmin)大于等于10的时候,当执行vacuum操作的时候会将此时表中记录的xmin置为特殊值FrozenXID。

  多次执行 select txid_current() 使得事务id增加。

postgres=# select txid_current();
 txid_current 
--------------
         2539
(1 row)

3. 查看数据

postgres=# select xmin,age(xmin),xmax,* from tb9;
 xmin | age | xmax | id | name 
------+-----+------+----+------
 2523 |  17 |    0 |  1 | aa
 2523 |  17 |    0 |  2 | aa
 2523 |  17 |    0 |  3 | aa
 2523 |  17 |    0 |  4 | aa
 2523 |  17 |    0 |  5 | aa
(5 rows)

看到xmin的事务年龄已经是17。

4. 执行vacuum操作

postgres=# vacuum tb9;
VACUUM

5. 再次查看数据

postgres=# select xmin,age(xmin),xmax,* from tb9;
 xmin |    age     | xmax | id | name 
------+------------+------+----+------
    2 | 2147483647 |    0 |  1 | aa
    2 | 2147483647 |    0 |  2 | aa
    2 | 2147483647 |    0 |  3 | aa
    2 | 2147483647 |    0 |  4 | aa
    2 | 2147483647 |    0 |  5 | aa
(5 rows)

  freeze后的tuple, xmin 变成了一个FrozenXID,这个XID不参与比较,始终认为这个ID比其他的XID老,所以用 age 去计算始终显示 2147483647 。

说明:
  当没有手动设置vacuum_freeze_min_age的值的时候,执行
vacuum freeze tb9;
强制使用freeze的效果是一样的。




参考:
http://blog.163.com/digoal@126/blog/static/163877040201211259497702/

### PostgreSQL 14 内部机制中的冻结概念 在PostgreSQL中,事务ID(XID)是一个有限大小的数据结构,在32位系统上占用4字节空间。每当创建新事务时,都会分配一个新的XID。由于存储限制,旧的XIDs可能会被重用。为了防止这种重用导致数据不一致或丢失,PostgreSQL引入了冻结(Freezing)的概念[^1]。 #### 冻结的目的 当一条记录长时间未更新且其原始XID接近可重用范围时,该记录会被标记为已冻结。这表示这条记录属于一个非常古老的事务,并且不再参与多版本并发控制(MVCC)。通过这种方式,即使未来的事务ID循环回到相同的数值区间,也不会误认为这些古老记录是新的事务的一部分。 #### 如何执行冻结操作 通常情况下,VACUUM进程会自动处理这一过程。它扫描表并识别哪些元组需要转换成永久状态即“冷冻”。如果发现某个页面上的所有可见XID都已经超过了特定阈值,则整个页面都将被打上冻标签;否则只会单独修改符合条件的行项。此外,还有专门用于批量处理大量待冻结对象的大规模冻结工具——`CLUSTER`命令以及在线大规模冻结功能。 #### 解决与冻结有关的问题 有时会出现因为频繁写入而导致某些表无法及时完成必要的真空清理工作的情况,进而引发所谓的“冻结灾难”,这时就需要采取措施来缓解: - **调整参数配置**:可以通过增加`vacuum_freeze_min_age``autovacuum_vacuum_scale_factor`等参数值来减少不必要的冻结频率。 - **手动触发VACUUM FULL**:对于特别繁忙或者体积庞大的表格,可以考虑定期运行全量清理以确保不会累积过多等待冻结的对象。 - **优化查询性能**:提高应用程序本身的效率也有助于降低对底层数据库的压力,从而间接改善因高负载引起的各种问题包括但不限于冻结延迟现象的发生概率. ```sql -- 手动启动一次完整的VACUUM操作 VACUUM (FULL, FREEZE) table_name; ```
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值