支援版本:目前 (17) / 16 / 15 / 14 / 13
開發版本:devel
不支援版本:12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0 / 8.4 / 8.3 / 8.2 / 8.1 / 8.0 / 7.4

52.12. pg_locks #

視窗 pg_locks 提供了資料庫伺服器中,作用中的處理程序所持有的鎖定資訊。有關鎖定的更多討論,請參閱第 13 章

pg_locks 針對每個作用中的可鎖定物件、請求的鎖定模式和相關處理程序,包含一個資料列。因此,如果多個處理程序正在持有或等待鎖定同一物件,則同一可鎖定物件可能會出現多次。但是,目前沒有任何鎖定的物件根本不會出現。

有幾種不同類型的可鎖定物件:整個關聯(例如,資料表)、關聯的個別頁面、關聯的個別元組、交易 ID(虛擬 ID 和永久 ID)和一般資料庫物件(由類別 OID 和物件 OID 識別,與 pg_descriptionpg_depend 中的方式相同)。此外,擴充關聯的權利被表示為一個獨立的可鎖定物件,更新 pg_database.datfrozenxid 的權利也是如此。此外,可以在具有使用者定義含義的數字上取得「建議」鎖定。

表 52.12. pg_locks 資料欄

資料欄類型

說明

locktype text

可鎖定物件的類型:relationextendfrozenidpagetupletransactionidvirtualxidspectokenobjectuserlockadvisoryapplytransaction。(另請參閱表 27.11。)

database oid(參考 pg_database.oid

鎖定目標所在的資料庫的 OID,如果目標是共用物件,則為零;如果目標是交易 ID,則為 null

relation oid(參考 pg_class.oid

鎖定目標關聯的 OID,如果目標不是關聯或關聯的一部分,則為 null

page int4

關聯中鎖定目標的頁碼,如果目標不是關聯頁面或元組,則為 null

tuple int2

頁面中鎖定目標的元組編號,如果目標不是元組,則為 null

virtualxid text

鎖定目標交易的虛擬 ID,如果目標不是虛擬交易 ID,則為 null;請參閱第 66 章

transactionid xid

鎖定目標交易的 ID,如果目標不是交易 ID,則為 null;第 66 章

classid oid(參考 pg_class.oid

包含鎖定目標的系統目錄的 OID,如果目標不是一般資料庫物件,則為 null

objid oid(參考任何 OID 資料欄)

系統目錄中鎖定目標的 OID,如果目標不是一般資料庫物件,則為 null

objsubid int2

鎖定目標的資料欄編號(classidobjid 參考資料表本身),如果目標是其他一般資料庫物件,則為零;如果目標不是一般資料庫物件,則為 null

virtualtransaction text

持有或等待此鎖定的交易的虛擬 ID

pid int4

持有或等待此鎖定的伺服器處理程序的處理程序 ID,如果鎖定由已準備的交易持有,則為 null

mode text

此處理程序持有或希望的鎖定模式名稱(請參閱第 13.3.1 節第 13.2.3 節

granted bool

如果持有鎖定則為 True,如果等待鎖定則為 False

fastpath bool

如果鎖定透過快速路徑取得則為 True,如果透過主要鎖定表取得則為 False

waitstart timestamptz

伺服器程序開始等待此鎖定的時間,如果鎖定已被持有則為 null。 請注意,即使 grantedfalse,等待開始後的一段非常短的時間內,此值也可能為 null。


如果某列代表由指定的程序持有的鎖定,則 granted 為 true。 False 表示此程序目前正在等待取得此鎖定,這意味著至少還有另一個程序正在持有或等待在同一個可鎖定物件上發生衝突的鎖定模式。 等待中的程序將會進入睡眠狀態,直到其他鎖定被釋放(或偵測到死鎖情況)。 單一程序一次最多只能等待取得一個鎖定。

在執行交易的過程中,伺服器程序會持有交易的虛擬交易 ID 的獨佔鎖定。 如果為交易分配了永久 ID(通常只有在交易更改資料庫的狀態時才會發生),則它也會持有交易的永久交易 ID 的獨佔鎖定,直到交易結束。 當程序發現有必要專門等待另一個交易結束時,它會嘗試取得另一個交易的 ID(虛擬 ID 或永久 ID,取決於情況)的共享鎖定。 只有在另一個交易終止並釋放其鎖定時,該操作才會成功。

雖然元組是一種可鎖定的物件類型,但關於列層級鎖定的資訊儲存在磁碟上,而不是在記憶體中,因此列層級鎖定通常不會出現在此檢視中。 如果程序正在等待列層級鎖定,它通常會在此檢視中顯示為正在等待該列鎖定的當前持有者的永久交易 ID。

推測性插入鎖定包含交易 ID 和推測性插入權杖。 推測性插入權杖顯示在 objid 欄位中。

諮詢鎖定可以透過由單個 bigint 值或兩個整數值組成的鍵取得。 bigint 鍵的高位半部顯示在 classid 欄位中,低位半部顯示在 objid 欄位中,並且 objsubid 等於 1。原始的 bigint 值可以使用表示式 (classid::bigint << 32) | objid::bigint 重新組合。 整數鍵的顯示方式是:第一個鍵在 classid 欄位中,第二個鍵在 objid 欄位中,並且 objsubid 等於 2。 鍵的實際意義取決於使用者。 諮詢鎖定是每個資料庫的本機鎖定,因此 database 欄位對於諮詢鎖定有意義。

套用交易鎖定用於平行模式,以便在邏輯複寫中套用交易。 遠端交易 ID 顯示在 transactionid 欄位中。 objsubid 顯示鎖定的子類型,其中 0 用於同步變更集的鎖定,而 1 用於等待交易完成以確保提交順序的鎖定。

pg_locks 提供了資料庫叢集中所有鎖定的全域檢視,而不僅僅是與目前資料庫相關的鎖定。 雖然它的 relation 欄位可以與 pg_class.oid 進行聯結,以識別鎖定的關聯,但這僅適用於目前資料庫中的關聯(database 欄位是目前資料庫的 OID 或零的那些關聯)。

pid 欄位可以與 pg_stat_activity 檢視的 pid 欄位進行聯結,以取得關於持有或等待每個鎖定的會話的更多資訊,例如

SELECT * FROM pg_locks pl LEFT JOIN pg_stat_activity psa
    ON pl.pid = psa.pid;

此外,如果您正在使用預備交易,則 virtualtransaction 欄位可以與 pg_prepared_xacts 檢視的 transaction 欄位進行聯結,以取得關於持有鎖定的預備交易的更多資訊。(預備交易永遠不會等待鎖定,但它會繼續持有它在執行時取得的鎖定。)例如

SELECT * FROM pg_locks pl LEFT JOIN pg_prepared_xacts ppx
    ON pl.virtualtransaction = '-1/' || ppx.transaction;

雖然可以透過將 pg_locks 與自身聯結來取得關於哪些程序封鎖了其他哪些程序的資訊,但在細節上很難做到正確。 這樣的查詢必須對哪些鎖定模式與哪些其他鎖定模式衝突的知識進行編碼。 更糟的是,pg_locks 檢視不會公開關於哪些程序在鎖定等待佇列中領先於哪些其他程序的資訊,也不會公開關於哪些程序是代表哪些其他客戶端會話執行的平行工作者程序的資訊。 最好使用 pg_blocking_pids() 函數(請參閱 表 9.69)來識別等待程序被哪些程序封鎖。

pg_locks 檢視顯示來自一般鎖定管理員和謂詞鎖定管理員的資料,它們是獨立的系統;此外,一般鎖定管理員將其鎖定細分為一般鎖定和快速路徑鎖定。 此資料不能保證完全一致。 查詢此檢視時,會一次一個地從每個後端收集關於快速路徑鎖定的資料(fastpath = true),而不會凍結整個鎖定管理員的狀態,因此在收集資訊時可能會取得或釋放鎖定。 但是請注意,已知這些鎖定與目前已存在的任何其他鎖定不衝突。 在查詢完所有後端的快速路徑鎖定後,其餘的一般鎖定管理員會作為一個單元鎖定,並且會以原子操作的方式收集所有剩餘鎖定的一致快照。 在解除鎖定一般鎖定管理員後,謂詞鎖定管理員也會以類似的方式鎖定,並且會以原子操作的方式收集所有謂詞鎖定。 因此,除了快速路徑鎖定之外,每個鎖定管理員都會提供一組一致的結果,但由於我們沒有同時鎖定兩個鎖定管理員,因此有可能在我們查詢完一般鎖定管理員之後和查詢謂詞鎖定管理員之前取得或釋放鎖定。

如果非常頻繁地存取此檢視,則鎖定一般鎖定管理員和/或謂詞鎖定管理員可能會對資料庫效能產生一些影響。 鎖定僅保持在從鎖定管理員取得資料所需的最小時間內,但這並不能完全消除對效能產生影響的可能性。

提交更正

如果您在文件中發現任何不正確、與特定功能的經驗不符或需要進一步澄清的內容,請使用此表格來報告文件問題。