

# 执行手动 vacuum 冻结
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum.VacuumFreeze"></a>

您可能需要对已具有正在运行的 vacuum 进程的表执行手动 vacuum 操作。如果您已使用接近 20 亿个事务（或高于您监控的任何阈值）的期限标识表，则这会很有用。

以下步骤是指导原则，此过程存在几种变化。例如，在测试期间，假设您发现设定的 [https://www.postgresql.org/docs/current/static/runtime-config-resource.html#GUC-MAINTENANCE-WORK-MEM](https://www.postgresql.org/docs/current/static/runtime-config-resource.html#GUC-MAINTENANCE-WORK-MEM) 参数值过小，并且您需要立即对表采取措施。不过，可能您不希望此时恢复实例。通过使用前几节中的查询，您可以确定哪个表存在问题，并找到长时间运行的 Autovacuum 会话。您知道您需要更改 `maintenance_work_mem` 参数设置，但您还需要立即采取行动，对有问题的表执行 vacuum 操作。以下过程说明了在此情况下应采取的措施。

**手动执行 vacuum 冻结**

1. 打开针对包含要执行 vacuum 操作的表的数据库的两个会话。对于第二个会话，使用“screen”或其他维护会话的实用工具 (如果您的连接已中断)。

1. 在第一个会话中，获取正在表上运行的 autovacuum 会话的进程 ID (PID)。

   运行以下查询可获取 Autovacuum 会话的 PID。

   ```
   SELECT datname, usename, pid, current_timestamp - xact_start 
   AS xact_runtime, query
   FROM pg_stat_activity WHERE upper(query) LIKE '%VACUUM%' ORDER BY 
   xact_start;
   ```

1. 在第二个会话中，计算该操作所需的内存量。在此示例中，我们确定自己最多可以为该操作使用 2GB 的内存，因此，我们将当前会话的 [https://www.postgresql.org/docs/current/static/runtime-config-resource.html#GUC-MAINTENANCE-WORK-MEM](https://www.postgresql.org/docs/current/static/runtime-config-resource.html#GUC-MAINTENANCE-WORK-MEM) 设置为 2 GB。

   ```
   SET maintenance_work_mem='2 GB';
   SET
   ```

1. 在第二个会话中，为表发出 `vacuum freeze verbose` 命令。详细设置很有用，因为虽然 PostgreSQL 中当前没有进度报告，但您可以查看活动。

   ```
   \timing on
   Timing is on.
   vacuum freeze verbose pgbench_branches;
   ```

   ```
   INFO:  vacuuming "public.pgbench_branches"
   INFO:  index "pgbench_branches_pkey" now contains 50 row versions in 2 pages
   DETAIL:  0 index row versions were removed.
   0 index pages have been deleted, 0 are currently reusable.
   CPU 0.00s/0.00u sec elapsed 0.00 sec.
   INFO:  index "pgbench_branches_test_index" now contains 50 row versions in 2 pages
   DETAIL:  0 index row versions were removed.
   0 index pages have been deleted, 0 are currently reusable.
   CPU 0.00s/0.00u sec elapsed 0.00 sec.
   INFO:  "pgbench_branches": found 0 removable, 50 nonremovable row versions 
        in 43 out of 43 pages
   DETAIL:  0 dead row versions cannot be removed yet.
   There were 9347 unused item pointers.
   0 pages are entirely empty.
   CPU 0.00s/0.00u sec elapsed 0.00 sec.
   VACUUM
   Time: 2.765 ms
   ```

1. 在第一个会话中，如果 autovacuum 阻止 vacuum 会话，`pg_stat_activity` 显示 vacuum 会话的等待为 `T`。在此情况下，您需要终止 autovacuum 进程，如下所示。

   ```
   SELECT pg_terminate_backend('the_pid'); 
   ```
**注意**  
某些较低版本的 Amazon RDS 无法使用上述命令终止 autovacuum 进程，并且会失败，显示以下错误：`ERROR: 42501: must be a superuser to terminate superuser process LOCATION: pg_terminate_backend, signalfuncs.c:227`。

   此时，您的会话将开始。由于此表可能位于其工作列表中的最高位置，因此 Autovacuum 将立即重新启动。

1. 在第二个会话中启动您的 `vacuum freeze verbose` 命令，然后终止第一个会话中的 autovacuum 过程。