跳转到内容

PostgreSQL/Vacuum

来自维基教科书,开放的书籍,开放的世界


消除膨胀

[编辑 | 编辑源代码]

正如我们在 MVCC 章中所看到的,数据库会因为 膨胀 而占用越来越多的磁盘空间:随着时间的推移,逻辑上删除但物理上仍然存在的旧行版本会越来越多地出现在堆和索引文件中。本章将解释 SQL 命令 VACUUM 和自动运行的 Autovacuum 进程如何清理文件,从而防止它们无限制地增长。

实例中的一个进程是 Autovacuum 守护进程。它会根据统计收集器收集的值持续监控所有数据库的状态,并在检测到某些情况时启动 Autovacuum 进程,例如:表中存在大量修改。这导致了 PostgreSQL 预期的动态行为:只有在必要时,Autovauum 才会清理文件。此外,客户端进程可以在任何时候发出 SQL 命令 VACUUM。DBA 会在他们识别出关键情况时进行交互式操作,或者在定期运行的批处理作业中启动它。在大多数情况下,由于 Autovacuum 守护进程不断运行,因此不需要这样做。

用来确定哪些物理存在的行版本不再需要的中心值是 xmax,它显示哪个事务删除了该行。消除操作必须根据必须同时适用的几个标准来评估它

  • xmax 必须不为零,因为值为零表示该行版本没有被删除。
  • xmax 必须包含一个比所有当前运行的事务的最旧 XID 更旧的 XID。这保证了没有现有或即将到来的事务会对该行版本进行读或写访问。
  • xmax 的事务必须已提交。如果它仍在运行或被回滚,则此行版本将被视为有效(未删除)。
  • 如果存在行版本属于多个事务的情况,则需要采取更多措施。

当 vacuum 操作检测到这样的过时行版本时,它会将其空间标记为可供将来写入操作使用,优化页面上剩余版本在物理上的排列方式,并删除指向已删除行版本的索引元组。但只有在极少数情况下(或在 VACUUM FULL 的情况下),才会将此空间释放给操作系统。在大多数情况下,它仍然被数据库占用,并将被未来的 INSERT、UPDATE 或 DELETE 命令使用。因此,即使 Autovacuum 运行成功,文件的大小也不会缩小;但它们会有更多或更大的一些“洞”,将来可以存储数据。只有在这些“洞空间”被耗尽(每页)之后,才需要从操作系统中申请新的磁盘空间来存储新数据。

SQL 命令 VACUUM FULL 是这种保守行为的例外。它会在操作系统级别创建一个新文件,将所有有效的行版本复制到该文件中,并忽略“洞”,从而不留任何额外空间,然后删除旧文件。但它速度较慢,并且需要对受影响的表进行独占锁。

由于 vacuum 操作通常是 I/O 密集型操作,这可能会阻碍其他活动,因此 Autovacuum 会避免批量执行许多 vacuum 操作。相反,它会执行许多小的操作,并在操作之间设置时间延迟。SQL 命令 VACUUM 会立即运行,没有任何时间延迟。

更多操作

[编辑 | 编辑源代码]

VACUUM 以及 Autovacuum 不仅会消除 膨胀。它们还会执行其他任务,以最大程度地减少自身以及其他进程在未来进行 I/O 操作的活动。由于在大多数情况下,对页面的昂贵物理访问已经完成,因此可以非常有效地完成这项额外工作。其他操作包括

  • 冻结:它将某些行版本标记为冻结。这意味着它们被视为永远“有效”(可见),与 wraparound 问题无关(见后)。
  • 可见性映射和空闲空间映射:它会将有关处理过的页面状态的信息记录到两个额外的文件中,即 可见性映射空闲空间映射
  • 统计信息:与 统计信息收集器 相似,它会收集有关每个表的行数、值的分布等的统计信息,作为查询规划器决策的基础。
[编辑 | 编辑源代码]

关于 VACUUM 的 PostgreSQL 文档


华夏公益教科书