2025年9月25日: PostgreSQL 18 釋出!
支援的版本: 當前 (18) / 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

53.13. pg_locks #

檢視 pg_locks 提供對資料庫伺服器中活動程序所持鎖的資訊的訪問。有關鎖的更多討論,請參閱 第 13 章

pg_locks 包含每個活動的可鎖定物件、請求的鎖模式以及相關程序的一行。因此,同一個可鎖定物件可能會出現多次,如果多個程序正在持有或等待其上的鎖。但是,當前沒有任何鎖的物件將完全不會出現。

有幾種不同型別的可鎖定物件:整個關係(例如表)、關係的單個頁面、關係的單個元組、事務 ID(虛擬和永久 ID)以及通用資料庫物件(由類 OID 和物件 OID 標識,方式與 pg_descriptionpg_depend 中的方式相同)。此外,擴充套件關係的許可權被表示為一個獨立的可鎖定物件,更新 pg_database.datfrozenxid 的許可權也是如此。此外,還可以對使用者定義的數字進行“advisory”鎖。

表 53.13. 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;請參閱 第 67 章

transactionid xid

鎖所針對的事務的 ID,如果目標不是事務 ID 則為 NULL;第 67 章

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 列中。

Advisory 鎖可以基於由單個 bigint 值或兩個整數值組成的鍵來獲取。一個 bigint 鍵在其高位部分顯示在 classid 列中,其低位部分顯示在 objid 列中,objsubid 等於 1。可以使用表示式 (classid::bigint << 32) | objid::bigint 重新組合原始 bigint 值。整數鍵顯示為第一個鍵在 classid 列中,第二個鍵在 objid 列中,objsubid 等於 2。鍵的實際含義由使用者決定。Advisory 鎖在每個資料庫中都是本地的,因此 database 列對於 advisory 鎖是有意義的。

Apply transaction 鎖用於並行模式以應用邏輯複製中的事務。遠端事務 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.71)來識別等待程序正在等待的程序。

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

如果此檢視被頻繁訪問,鎖定常規鎖管理器和/或謂詞鎖管理器可能會對資料庫效能產生一定影響。鎖只保持必要的最短時間以從鎖管理器獲取資料,但這並不能完全消除效能影響的可能性。

提交更正

如果您在文件中發現任何不正確之處、與特定功能的實際使用不符之處,或者需要進一步澄清之處,請使用 此表單 報告文件問題。