

# 在 Autovacuum 正在运行时重新为表建立索引
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum.Reindexing"></a>

如果索引已损坏，Autovacuum 将继续处理表并失败。在此情况下，如果您尝试执行手动 vacuum 操作，您将收到一条与以下内容类似的错误消息。

```
postgres=>  vacuum freeze pgbench_branches;
ERROR: index "pgbench_branches_test_index" contains unexpected 
   zero page at block 30521
HINT: Please REINDEX it.
```

当索引损坏并且 autovacuum 尝试在表上运行时，您将处理已经正在运行的 autovacuum 会话。在您发出 [REINDEX](https://www.postgresql.org/docs/current/static/sql-reindex.html) 命令时，将删除表上的排他锁。将阻止写入操作以及使用该特定索引的读取操作。

**在对表运行 Autovacuum 时重新为表建立索引**

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

1. 在第一个会话中，获取正在表上运行的 Autovacuum 会话的 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. 在第二个会话中，发出 reindex 命令。

   ```
   \timing on
   Timing is on.
   reindex index pgbench_branches_test_index;
   REINDEX
     Time: 9.966 ms
   ```

1. 在第一个会话中，如果 autovacuum 阻止该过程，您将在 `pg_stat_activity` 中看到 vacuum 会话的等待为“T”。在此情况下，您将终止 autovacuum 过程。

   ```
   SELECT pg_terminate_backend('the_pid');
   ```

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

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