《postgresql指南--内幕探索》第六章 清理过程

清理过程(通常简称为VACUUM)是一种维护过程,有助于 PostgreSQL 的持久运行。它的两个主要任务是删除死元组,以及冻结事务标识。

为了移除死元组,清理过程有两种模式,分别是并发清理与完整清理。并发清理过程会删除表文件每个页面中的死元组,而其他事务可以在其运行时继续读取该表。相反,完整清理不仅会移除整个文件中所有的死元组,还会对整个文件中所有的活元组进行碎片整理。其他事务在完整清理运行时无法访问该表。

尽管清理过程对PostgreSQL至关重要,但与其他功能相比,它的改进相对其他功能而言要慢一些。例如在8.0版本之前,清理过程必须手动执行(通过psql 实用程序或使用 cron 守护进程)。直到2005年实现了autovacuum 守护进程时,这一过程才实现了自动化。

由于清理过程涉及全表扫描,因此该过程代价高昂。在版本8.4(2009)中引入了可见性映射( Visibility Map,VM)来提高移除死元组的效率。在版本9.6(2016)中增强了 VM,从而改善了冻结过程的表现。

并发清理概述

清理过程为指定的表或数据库中的所有表执行以下任务。

1.移除死元组和对活元组进行碎片整理。

  • 移除每一页中的死元组,并对每一页内的活元组进行碎片整理。
  • 移除指向死元组的索引元组。

2.冻结旧的事务标识。

  • 如有必要,冻结旧元组的事务标识。
  • 更新与冻结事务标识相关的系统视图( pg_database 与 pg_class)。
  • 如果可能,移除不必要的提交日志文件。

3.其他。

  • 更新已处理表的空闲空间映射(FSM)和可见性映射(VM)。
  • 更新一些统计信息( pg_stat_all_tables 等)。

以下伪代码描述了清理的过程。

(1)      FOR each table
(2)          在目标表上获取 ShareUpdateExclusiveLock 锁 /* 允许其他事务对该表进行读取 */

             /* 第一部分 */
(3)          扫描所有页面,定位死元组,如有必要,冻结过早的元组
(4)          如果存在,移除指向死元组的索引元组

             /* 第二部分 */
(5)          FOR each page of the table
(6)               移除死元组,重排本页内的活元组
(7)               逐页更新目标表页对应的 FSM 与 VM
             END FOR

               /* 第三部分 */
(8)          如果最后一个页面没有任何元组,截断最后的页面
(9)          更新系统数据字典与统计信息
               释放ShareUpdateExclusiveLock锁
          END FOR

          /* 后续处理 */
(10)     更新统计信息与系统数据字典
(11)     如果可能,移除非必要的文件及CLOG中的文件

该伪码分为两大块:一块是依次处理表的循环,一块是后处理逻辑。而循环块又分为三个部分,每一个部分都有各自的任务。接下来会描述这三个部分及后处理的逻辑。

第一部分

这一部分执行冻结处理,并删除指向死元组的索引元组。

首先,PostgreSQL 扫描目标表以构建死元组列表,如果可能的话,还会冻结旧元组。该列表存储在本地内存中的 maintenance_work_mem 里(维护用的工作内存)。冻结过程将在下文中介绍。

扫描完成后,PostgreSQL 根据构建得到的死元组列表来删除索引元组。该过程在内部被称为“清除阶段”。不用说,该过程代价高昂。在 10.0 或更低版本中始终会执行清除阶段。在 11.0 或更高版本中,如果目标索引是B树,是否执行清除阶段由配置参数 vacuum_cleanup_index_scale_factor 决定。详细信息请参考此参数的说明。

当 maintenance_work_mem 已满,且未完成全部扫描时,PostgreSQL继续进行后续任务,即步骤(4)到(7),完成后再重新返回步骤(3)并继续扫描。

第二部分

这一部分会移除死元组,并逐页更新 FSM 和 VM。
在这里插入图片描述
假设该表包含三个页面,首先关注 0 号页面(即第一个页面),该页面包含三条元组, 其中 Tuple_2 是一条死元组,如图中 (1)所示。在这里PostgreSQL 移除了 Tuple_2,并重排剩余元组来整理碎片空间,然后更新该页面的 FSM 和 VM,如图中(2)所示。PostgreSQL 不断重复该过程直至最后一页。注意,非必要的行指针是不会被移除的,它们会在将来被重用。因为如果移除了行指针,就必须同时更新所有相关索引中的索引元组。

第三部分

第三部分会针对每个表,更新与清理过程相关的统计信息和系统视图。此外,如果最后一页中没有元组,则该页会从表文件中被截断。

后续处理

当处理完成后,Postgre

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值