Lock:Relation - Amazon Aurora

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

Lock:Relation

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

支援的引擎版本

所有版本的 Aurora Postgre 都支援此等待事件資訊SQL。

Context

大多數 PostgreSQL 命令隱含使用 鎖定來控制資料表中資料的並行存取。您也可以在應用程式碼中使用 LOCK 命令,以明確使用這些鎖定。許多鎖定模式彼此不相容,在嘗試存取同一個物件時,可能封鎖交易。發生這種情況時,Aurora PostgreSQL 會產生Lock:Relation事件。以下是一些常見例子:

  • 獨佔鎖定 (例如 ACCESS EXCLUSIVE) 會封鎖所有並行存取。資料定義語言 (DDL) 操作,例如隱含的 DROP TABLEVACUUM FULLTRUNCATECLUSTER取得ACCESS EXCLUSIVE鎖定。 ACCESS EXCLUSIVE 也是未明確指定模式之LOCK TABLE陳述式的預設鎖定模式。

  • 在資料表CREATE INDEX (without CONCURRENT)上使用 與INSERT取得ROW EXCLUSIVE鎖定的資料處理語言 (DML) 陳述式 DELETEUPDATE和 發生衝突。

如需資料表層級鎖定和衝突鎖定模式的詳細資訊,請參閱 PostgreSQL 文件中的明確鎖定

引起封鎖的查詢和交易通常透過下列其中一種方法解除封鎖:

  • 引起封鎖的查詢 — 由應用程式取消查詢,或由使用者結束程序。透過工作階段的陳述式逾時或死鎖偵測機制,引擎也可以強制結束查詢。

  • 引起封鎖的交易 — 交易執行 ROLLBACKCOMMIT 陳述式來停止封鎖。當工作階段由用戶端或因為網路問題而中斷連線時,或工作階段結束時,也會自動復原。資料庫引擎關閉、系統記憶體不足等原因會結束工作階段。

等待時間增加的可能原因

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

資料表鎖定發生衝突的並行工作階段變多

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

維護操作

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

鎖定讀取器執行個體

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

動作

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

降低封鎖SQL陳述式的影響

若要降低封鎖SQL陳述式的影響,請盡可能修改您的應用程式程式碼。以下是減少封鎖的兩種常用技巧:

  • 使用 NOWAIT選項 – 某些SQL命令,例如 SELECTLOCK陳述式,支援此選項。如果無法立即獲得鎖定,NOWAIT 指令會取消提出鎖定請求的查詢。這項技巧有助於避免引起封鎖的工作階段背後堆積被封鎖的工作階段。

    例如:假設交易 A 等待的鎖定由交易 B 持有。現在,如果 B 請求鎖定的資料表由交易 C 鎖定,則可能封鎖交易 A,直到交易 C 完成為止。但是,如果交易 B 請求鎖定 C 時使用 NOWAIT,則會很快失敗,以確保交易 A 不必無限期等待。

  • 使用 SET lock_timeout – 設定lock_timeout值以限制SQL陳述式在關係上取得鎖定的等待時間。如果未在指定的逾時內取得鎖定,則請求鎖定的交易會取消。請在工作階段層級設定此值。

將維護操作的影響降至最低

維護操作很重要,例如 VACUUMANALYZE。建議不要因為發現這些維護操作相關的 Lock:Relation 等待事件而關閉維護。下列方法可以將這些操作的影響降至最低:

  • 在離峰時段手動執行維護操作。

  • 若要減少 Lock:Relation 等待,請執行任何所需的自動資料清理調校。如需調整自動清空的相關資訊,請參閱 Amazon RDS使用者指南 中的在 Amazon 上使用 PostgreSQL 自動清空RDS

檢查讀取器鎖定

您可以檢查寫入器和讀取器上的並行工作階段是否持有相互封鎖的鎖定。作法是執行傳回鎖類型和關聯的查詢。在表格中,您可以找到兩個此類並行工作階段的一系列查詢,即寫入器工作階段和讀取器工作階段。

重播程序會等待 的持續時間,max_standby_streaming_delay然後再取消讀取器查詢。如範例所示,100ms 的鎖定逾時遠低於預設 max_standby_streaming_delay 的 30 秒。鎖定在出現問題之前逾時。

序列事件 Session (工作階段) 命令或輸出

設定READER使用指定值呼叫的環境變數,並嘗試使用此端點連線至資料庫執行個體。

讀取器工作階段

CLI 命令:

export READER=aurorapg2.12345678910.us-west-1.rds.amazonaws.com psql -h $READER

輸出:

psql (15devel, server 10.14)
Type "help" for help.

設定名為 WRITER 的環境變數,並嘗試使用此端點 連線至資料庫執行個體。

寫入器工作階段

CLI 命令:

export WRITER=aurorapg1.12345678910.us-west-1.rds.amazonaws.com psql -h $WRITER

輸出:

psql (15devel, server 10.14) 
Type "help" for help. 

寫入器工作階段會在寫入器執行個體上建立資料表 t1。

寫入器工作階段

PostgreSQL 查詢:

postgres=> CREATE TABLE t1(b integer); CREATE TABLE

如果寫入器上沒有衝突的查詢,則會立即在寫入器上取得ACCESSEXCLUSIVE鎖定。

寫入器工作階段

ACCESS EXCLUSIVE 鎖定已啟用

讀取器工作階段設定 100 毫秒的鎖定逾時間隔。

讀取器工作階段

PostgreSQL 查詢:

postgres=> SET lock_timeout=100; SET

讀取器工作階段會嘗試從讀取器執行個體上的資料表 t1 讀取資料。

讀取器工作階段

PostgreSQL 查詢:

postgres=> SELECT * FROM t1;

輸出範例:

b
---
(0 rows)

寫入器工作階段會捨棄 t1。

寫入器工作階段

PostgreSQL 查詢:

postgres=> BEGIN; BEGIN postgres=> DROP TABLE t1; DROP TABLE postgres=>

在讀取器上,查詢逾時,已取消。

讀取器工作階段

PostgreSQL 查詢:

postgres=> SELECT * FROM t1;

輸出範例:

ERROR:  canceling statement due to lock timeout
LINE 1: SELECT * FROM t1;
                      ^

若要判斷錯誤的原因。讀取器工作階段查詢pg_lockspg_stat_activity

讀取器工作階段

PostgreSQL 查詢:

postgres=> SELECT locktype, relation, mode, backend_type postgres=> FROM pg_locks l, pg_stat_activity t1 postgres=> WHERE l.pid=t1.pid AND relation = 't1'::regclass::oid;

結果表示aurora wal replay程序在資料表 t1 上保持ACCESS EXCLUSIVE鎖定。

讀取器工作階段

查詢結果:

locktype | relation | mode | backend_type ----------+----------+---------------------+------------------- relation | 68628525 | AccessExclusiveLock | aurora wal replay (1 row)