

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 解決 RDS for PostgreSQL 中無法識別的清空封鎖程式
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Unidentifiable_blockers"></a>

本節會探索其他可能阻止清空進行的原因。`postgres_get_av_diag()` 函數目前無法直接識別這些問題。

**Topics**
+ [無效的頁面](#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Invalid_pages)
+ [索引不一致](#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Index_inconsistency)
+ [異常高的交易速率](#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.High_transaction_rate)

## 無效的頁面
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Invalid_pages"></a>

當 PostgreSQL 在存取頁面時偵測到頁面檢查總和不相符時，會發生無效的頁面錯誤。內容無法讀取，防止自動清空凍結元組。這會有效停止清除程序。下列錯誤會寫入 PostgreSQL 的日誌：

```
WARNING:  page verification failed, calculated checksum YYYYY but expected XXXX
ERROR:  invalid page in block ZZZZZ of relation base/XXXXX/XXXXX
CONTEXT:  automatic vacuum of table myschema.mytable
```

**判斷物件類型**

```
ERROR: invalid page in block 4305910 of relation base/16403/186752608 
WARNING: page verification failed, calculated checksum 50065 but expected 60033
```

從錯誤訊息中，路徑 `base/16403/186752608` 會提供下列資訊：
+ "base" 是 PostgreSQL 資料目錄下的目錄名稱。
+ "16403" 是資料庫 OID，您可以在 `pg_database` 系統目錄中查詢。
+ "186752608" 是 `relfilenode`，可用來查詢 `pg_class` 系統目錄中的結構描述和物件名稱。

透過檢查受影響資料庫中下列查詢的輸出，您可以判斷物件類型。下列查詢會擷取 OID 186752608 的物件資訊。將 OID 取代為與您所遇到錯誤相關的 OID。

```
SELECT
    relname AS object_name,
    relkind AS object_type,
    nspname AS schema_name
FROM
    pg_class c
    JOIN pg_namespace n ON c.relnamespace = n.oid
WHERE
    c.oid = 186752608;
```

如需詳細資訊，請參閱 PostgreSQL 文件 [https://www.postgresql.org/docs/current/catalog-pg-class.html](https://www.postgresql.org/docs/current/catalog-pg-class.html)，以了解所有支援的物件類型，如 `pg_class` 中的 `relkind` 欄所述。

**指引**

此問題最有效的解決方案取決於特定 Amazon RDS 執行個體的組態，以及受不一致頁面影響的資料類型。

**如果物件類型是索引：**

建議重建索引。
+ **使用 `CONCURRENTLY` 選項** – 在 PostgreSQL 第 12 版之前，重建索引需要獨佔資料表鎖定，以限制對資料表的存取。使用 PostgreSQL 第 12 版和更新版本時，`CONCURRENTLY` 選項允許資料列層級鎖定，以大幅改善資料表的可用性。以下是命令：

  ```
  REINDEX INDEX ix_name CONCURRENTLY;
  ```

  雖然 `CONCURRENTLY` 干擾性較低，但在忙碌的資料表上可能會變慢。如果可能，請考慮在低流量期間建立索引。

  如需詳細資訊，請參閱 PostgreSQL [REINDEX](https://www.postgresql.org/docs/current/sql-reindex.html) 文件。
+ **使用 `INDEX_CLEANUP FALSE` 選項** – 如果索引較大且估計需要大量時間才能完成，您可以在排除索引的同時執行手動 `VACUUM FREEZE` 來解除封鎖自動清空。此功能可在 PostgreSQL 第 12 版及更新版本中使用。

  略過索引可讓您略過不一致索引的清空程序，並減輕包圍問題。不過，這無法解決基本的無效頁面問題。若要完全處理和解決無效的頁面問題，您仍然需要重建索引。

**如果物件類型是具體化視觀表：**

如果具體化視觀表發生無效頁面錯誤，請登入受影響的資料庫並重新整理以解決無效頁面：

重新整理具體化視觀表：

```
REFRESH MATERIALIZED VIEW schema_name.materialized_view_name;
```

如果重新整理失敗，請嘗試重新建立：

```
DROP MATERIALIZED VIEW schema_name.materialized_view_name;
CREATE MATERIALIZED VIEW schema_name.materialized_view_name AS query;
```

重新整理或重新建立具體化視觀表會將其還原，而不會影響基礎資料表資料。

**對於所有其他物件類型：**

對於所有其他物件類型，請聯絡 AWS 支援。

## 索引不一致
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Index_inconsistency"></a>

邏輯上不一致的索引會防止自動清空進行。在索引的清空階段或 SQL 陳述式存取索引時，系統會記錄下列錯誤或類似錯誤。

```
ERROR: right sibling's left-link doesn't match:block 5 links to 10 instead of expected 2 in index ix_name
```

```
ERROR: failed to re-find parent key in index "XXXXXXXXXX" for deletion target page XXX
CONTEXT:  while vacuuming index index_name of relation schema.table
```

**指引**

在手動 `VACUUM FREEZE` 上使用 `INDEX_CLEANUP` 重建索引或略過索引。如需如何重建索引的資訊，請參閱[如果物件類型是索引](#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Invalid_pages)。
+ **使用 CONCURRENTLY 選項** – 在 PostgreSQL 第 12 版之前，重建索引需要獨佔資料表鎖定，以限制對資料表的存取。透過 PostgreSQL 第 12 版和更新版本，CONCURRENTLY 選項允許資料列層級鎖定，以大幅改善資料表的可用性。以下是命令：

  ```
  REINDEX INDEX ix_name CONCURRENTLY;
  ```

  雖然 CONCURRENTLY 干擾性較低，但在忙碌的資料表上可能會變慢。如果可能，請考慮在低流量期間建立索引。如需詳細資訊，請參閱 *PostgreSQL* 文件中的 [REINDEX](https://www.postgresql.org/docs/current/sql-reindex.html)。
+ **使用 INDEX\$1CLEANUP FALSE 選項** – 如果索引較大且估計需要大量時間才能完成，您可以在排除索引的同時執行手動 VACUUM FREEZE 來解除封鎖自動清空。此功能可在 PostgreSQL 第 12 版及更新版本中使用。

  略過索引可讓您略過不一致索引的清空程序，並減輕包圍問題。不過，這無法解決基本的無效頁面問題。若要完全處理和解決無效的頁面問題，您仍然需要重建索引。

## 異常高的交易速率
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.High_transaction_rate"></a>

在 PostgreSQL 中，高交易速率可能會大幅影響自動清空的效能，導致清除無效元組的速度變慢，並提高交易 ID 包圍的風險。您可以透過測量兩個時段之間的 `max(age(datfrozenxid))` 差異來監控交易速率，通常是每秒。此外，您可以使用 RDS Performance Insights 的下列計數器指標來測量交易速率 (xact\$1commit 和 xact\$1rollback 的總和)，這是交易的總數。


|  計數器  |  類型  |  單位  |  指標  | 
| --- | --- | --- | --- | 
|  xact\$1commit  |  交易  |  每秒遞交數  |  db.Transactions.xact\$1commit  | 
|  xact\$1rollback  |  交易  |  每秒轉返數  |  db.Transactions.xact\$1rollback  | 

快速增加表示交易負載很高，可能會自動清空不堪負荷，導致膨脹、鎖定爭用和潛在的效能問題。這可能會在幾個方面對自動清空程序產生負面影響：
+ **資料表活動：**正在清空的特定資料表可能遇到大量交易，因而導致延遲。
+ **系統資源**整體系統可能會超載，導致自動清空難以存取必要的資源以有效率地運作。

請考慮下列策略，以允許自動清空更有效地運作並跟上其任務：

1. 如果可能，請降低交易速率。考慮在可行的情況下批次處理或分組類似的交易。

1. 以經常更新的資料表為目標，在離峰時段內每夜、每週或每兩週手動 `VACUUM FREEZE` 操作一次。

1. 考慮擴展執行個體類別以配置更多系統資源，以處理高交易量和自動清空。