

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

# Lock:Relation
<a name="wait-event.lockrelation"></a>

`Lock:Relation` 事件表示查詢正在等待取得鎖定的資料表或檢視表 (關聯)，目前由另一個交易鎖定。

**Topics**
+ [支援的引擎版本](#wait-event.lockrelation.context.supported)
+ [Context](#wait-event.lockrelation.context)
+ [等待時間增加的可能原因](#wait-event.lockrelation.causes)
+ [動作](#wait-event.lockrelation.actions)

## 支援的引擎版本
<a name="wait-event.lockrelation.context.supported"></a>

所有 RDS for PostgreSQL 版本都支援此等待事件資訊。

## Context
<a name="wait-event.lockrelation.context"></a>

大多數 PostgreSQL 命令隱含地使用鎖定來控制並行存取資料表中的資料。您也可以在應用程式碼中使用 `LOCK` 命令，以明確使用這些鎖定。許多鎖定模式彼此不相容，在嘗試存取同一個物件時，可能封鎖交易。發生這種情況時，RDS for PostgreSQL 會產生 `Lock:Relation` 事件。以下是一些常見例子：
+ 獨佔鎖定 (例如 `ACCESS EXCLUSIVE`) 會封鎖所有並行存取。資料定義語言 (DDL) 操作 (例如 `DROP TABLE`、`TRUNCATE`、`VACUUM FULL` 及 `CLUSTER`) 隱含地取得 `ACCESS EXCLUSIVE` 鎖定。對於未明確指定模式的 `LOCK TABLE` 陳述式，`ACCESS EXCLUSIVE` 也是預設鎖定模式。
+ 在資料表上使用 `CREATE INDEX (without CONCURRENT)` 時，與取得 `ROW EXCLUSIVE` 鎖定的資料處理語言 (DML) 陳述式 `UPDATE`、`DELETE` 及 `INSERT` 會發生衝突。

如需表格層級鎖定和衝突鎖定模式的詳細資訊，請參閱 PostgreSQL 文件中的[明確鎖定](https://www.postgresql.org/docs/13/explicit-locking.html)。

引起封鎖的查詢和交易通常透過下列其中一種方法解除封鎖：
+ 引起封鎖的查詢 — 由應用程式取消查詢，或由使用者結束程序。透過工作階段的陳述式逾時或死鎖偵測機制，引擎也可以強制結束查詢。
+ 引起封鎖的交易 — 交易執行 `ROLLBACK` 或 `COMMIT` 陳述式來停止封鎖。當工作階段由用戶端或因為網路問題而中斷連線時，或工作階段結束時，也會自動復原。資料庫引擎關閉、系統記憶體不足等原因會結束工作階段。

## 等待時間增加的可能原因
<a name="wait-event.lockrelation.causes"></a>

當 `Lock:Relation` 事件發生頻率高於正常情況時，則可能表示效能問題。典型原因包括：

**資料表鎖定發生衝突的並行工作階段變多**  
以查詢來鎖定同一個資料表但鎖定模式衝突的並行工作階段可能變多。

**維護操作**  
運作狀態維護操作 (例如 `VACUUM` 和 `ANALYZE`) 可能大幅增加衝突鎖定的數量。`VACUUM FULL` 取得 `ACCESS EXCLUSIVE` 鎖定，`ANALYSE` 取得 `SHARE UPDATE EXCLUSIVE` 鎖定。這兩種鎖定都可能引起 `Lock:Relation` 等待事件。應用程式資料維護操作 (例如重新整理具體化檢視表) 也會使鎖定的查詢和交易增加。

**鎖定讀取器執行個體**  
寫入器和讀取器保有的關係鎖之間可能存在衝突。目前，只有 `ACCESS EXCLUSIVE` 關係鎖被複製到讀取器執行個體。但是，`ACCESS EXCLUSIVE` 關係鎖將與讀取器所持有的任何 `ACCESS SHARE` 關係鎖發生衝突。這可能會造成讀取器上的鎖定關係等待事件增加。

## 動作
<a name="wait-event.lockrelation.actions"></a>

根據等待事件的原因，我們會建議不同的動作。

**Topics**
+ [減少封鎖 SQL 陳述式的影響](#wait-event.lockrelation.actions.reduce-blocks)
+ [將維護操作的影響降至最低](#wait-event.lockrelation.actions.maintenance)

### 減少封鎖 SQL 陳述式的影響
<a name="wait-event.lockrelation.actions.reduce-blocks"></a>

若要減少封鎖 SQL 陳述式的影響，請盡可能修改應用程式碼。以下是減少封鎖的兩種常用技巧：
+ 使用 `NOWAIT` 選項 — 某些 SQL 命令支援此選項，例如 `SELECT` 和 `LOCK` 陳述式。如果無法立即獲得鎖定，`NOWAIT` 指令會取消提出鎖定請求的查詢。這項技巧有助於避免引起封鎖的工作階段背後堆積被封鎖的工作階段。

  例如：假設交易 A 等待的鎖定由交易 B 持有。現在，如果 B 請求鎖定的資料表由交易 C 鎖定，則可能封鎖交易 A，直到交易 C 完成為止。但是，如果交易 B 請求鎖定 C 時使用 `NOWAIT`，則會很快失敗，以確保交易 A 不必無限期等待。
+ 使用 `SET lock_timeout` - 設定 `lock_timeout` 值來限制 SQL 陳述式在關聯上取得鎖定所等待的時間。如果在指定的逾時內未獲得鎖定，則會取消提出鎖定請求的交易。請在工作階段層級設定此值。

### 將維護操作的影響降至最低
<a name="wait-event.lockrelation.actions.maintenance"></a>

維護操作很重要，例如 `VACUUM` 和 `ANALYZE`。建議不要因為發現這些維護操作相關的 `Lock:Relation` 等待事件而關閉維護。下列方法可以將這些操作的影響降至最低：
+ 在離峰時段手動執行維護操作。
+ 若要減少 `Lock:Relation` 等待，請執行任何所需的自動資料清理調校。如需調整自動清理的相關資訊，請參閱《Amazon RDS 使用者指南》**中的[在 Amazon RDS 上使用 PostgreSQL 自動資料清理](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Appendix.PostgreSQL.CommonDBATasks.Autovacuum.html)。