vacuum freeze

背景

PostgreSQL 目前默认的存储引擎,事务可见性需要依赖行头的事务号,因为事务号是32位的,会循环使用。

在一条记录产生后,如果再次经历了20亿个事务,必须对其进行freeze,否则数据库会认为这条记录是未来事务产生的(可见性判断)。

因此FREEZE操作是数据库在32位事务号的情况下,经常要做的。

对全表进行FREEZE操作时,会扫描整表,将大于指定阈值least(autovacuum_freeze_min_age, 表级参数vacuum_freeze_min_age)年龄的记录设置为freeze。可能导致大量的读IO,写IO(主要是写数据文件,WAL日志, full page write WAL)。

一些参数决定数据库在什么时候触发FREEZE,以及触发FREEZE时,冻结哪些记录,以及是否涉及到调度(sleep)。

同时很多参数有库级、表级选项。表级优先,然后是库级,最后是实例级。

《PostgreSQL GUC 参数级别介绍》

1、多久检查一次哪些表是否需要FREEZE

postgres=# show autovacuum_naptime ;    
 autovacuum_naptime     
--------------------    
 1s    
(1 row)    

 默认值是60s, 启动下一个autovacuum之前的等待时间:autovacuum_naptime= 60s(autovacuum_naptime/N)其中N是实例中数据库的总数,autovacuum_max_workers = 3 (Default)

2、哪些表需要被自动FREEZE,

超过如下阈值,如果设置了表级参数则以表级参数为准,否则以系统参数为准。

表级参数    
autovacuum_freeze_max_age    
autovacuum_freeze_table_age    
    
系统级参数    
autovacuum_freeze_max_age    

autovacuum_freeze_max_age=200000000(default) 

3、手工执行普通vacuum时,哪些表会被扫描全表,并freeze

超过如下阈值

系统级参数    
vacuum_freeze_table_age    

vacuum_freeze_table_age=150000000(default) 表的年龄大于此值时,会执行急切模式(扫描所有未全部冻结的页面,急切冻结的触发条件是pg_database.datfrozenxid<oldestxmin-vacuum_freeze_table_age;懒惰模式扫描所有存在死元祖的页面,即使某页有满足freeze的元祖但没有死元组的情况也不会扫描此页,冻结xmin小于freezelimit_txid的元组,freezelimit_txid的计算前面也提到过,freezelimit_txid=oldestxmin-vacuum_freeze_min_age)

注意,现在PG支持VM文件里面记录一个PAGE是否需要被FREEZE,所以即使全表扫描,也会根据VM标记位,跳过一些BLOCK,所以FREEZE并不一定会产生大量读IO。根据表的情况而定。

3、触发FREEZE时,哪些记录需要被FREEZE

超过如下阈值的记录被FREEZE,如果设置了表级参数则以表级参数为准,否则以系统参数为准。

表级参数    
autovacuum_freeze_min_age    
    
系统级参数    
vacuum_freeze_min_age    

vacuum_freeze_min_age= 50000000(default)

4、FREEZE后台进程的调度(sleep)。

  current_setting('autovacuum_vacuum_cost_delay') as v7,              -- 自动垃圾回收时, 每轮回收周期后的一个休息时间, 主要防止垃圾回收太耗资源. -1 表示沿用vacuum_cost_delay的设置    
  current_setting('autovacuum_vacuum_cost_limit') as v8,              -- 自动垃圾回收时, 每轮回收周期设多大限制, 限制由vacuum_cost_page_hit,vacuum_cost_page_missvacuum_cost_page_dirty参数以及周期内的操作决定. -1 表示沿用vacuum_cost_limit的设置    
  current_setting('vacuum_cost_delay') as v9,                         -- 手动垃圾回收时, 每轮回收周期后的一个休息时间, 主要防止垃圾回收太耗资源.    
  current_setting('vacuum_cost_limit') as v10,                        -- 手动垃圾回收时, 每轮回收周期设多大限制, 限制由vacuum_cost_page_hit,vacuum_cost_page_missvacuum_cost_page_dirty参数以及周期内的操作决定.    
  current_setting('autovacuum') as autovacuum                         -- 是否开启自动垃圾回收    

以下是用于调整autovacuum相关的IO参数:
• autovacuum_vacuum_cost_limit : autovacuum可达到的总成本限制(结合所有autovacuum作业)
• autovacuum_vacuum_cost_delay : 当一个清理工作达到autovacuum_vacuum_cost_limit指定的成本限制时,autovacuum将休眠数毫秒
• vacuum_cost_page_hit : 读取已在共享缓冲区中且不需要磁盘读取的页的成本.
• vacuum_cost_page_miss : 获取不在共享缓冲区中的页的成本.
• vacuum_cost_page_dirty : 在每一页中发现死元组时写入该页的成本.

谨慎设置autovacuum_max_workers:
• 通常,此成本平均分配给实例中运行的所有autovacuum过程的autovacuum_max_workers数。
• 因此,增加autovacuum_max_workers可能会延迟当前运行的autovacuum workers的autovacuum执行(workers增大平均分配给autovacumm的cost就少 时间就会延长)
• 而增加autovacuum_vacuum_cost_limit可能会导致IO瓶颈。
• 可以通过设置单个表的存储参数来重写此行为,这样会忽略全局设置。

 

参考:

https://www.modb.pro/db/26054

https://github.com/digoal/blog/blob/master/201804/20180411_01.md

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值