LOCK
— 鎖定表
LOCK [ TABLE ] [ ONLY ]name
[ * ] [, ...] [ INlockmode
MODE ] [ NOWAIT ] wherelockmode
is one of: ACCESS SHARE | ROW SHARE | ROW EXCLUSIVE | SHARE UPDATE EXCLUSIVE | SHARE | SHARE ROW EXCLUSIVE | EXCLUSIVE | ACCESS EXCLUSIVE
LOCK TABLE
獲取表級鎖,並在必要時等待任何衝突的鎖被釋放。如果指定了 NOWAIT
,則 LOCK TABLE
不會等待獲取所需的鎖:如果無法立即獲取,則命令中止併發出錯誤。一旦獲取,鎖將保持到當前事務的剩餘時間。(沒有 UNLOCK TABLE
命令;鎖總是在事務結束時釋放。)
當鎖定檢視時,檢視定義查詢中出現的所有關係都會以相同的鎖模式被遞迴鎖定。
在自動為引用表的命令獲取鎖時,PostgreSQL 始終使用盡可能低的限制性鎖模式。LOCK TABLE
適用於您可能需要更嚴格鎖定的情況。例如,假設一個應用程式在 READ COMMITTED
隔離級別下執行事務,並且需要確保表中的資料在事務期間保持穩定。為了實現這一點,您可以在查詢之前獲取表上的 SHARE
鎖模式。這將阻止併發資料更改,並確保後續對錶的讀取看到已提交資料的穩定檢視,因為 SHARE
鎖模式與寫入者獲取的 ROW EXCLUSIVE
鎖衝突,並且您的 LOCK TABLE
語句將等待任何併發的 name
IN SHARE MODEROW EXCLUSIVE
模式鎖持有者提交或回滾。因此,一旦您獲得鎖,就沒有未提交的寫入;此外,在您釋放鎖之前,也不會開始任何新的寫入。
要在 REPEATABLE READ
或 SERIALIZABLE
隔離級別下執行事務以達到類似效果,您必須在執行任何 SELECT
或資料修改語句之前執行 LOCK TABLE
語句。此型別事務的資料檢視將在其第一個 SELECT
或資料修改語句開始時凍結。LOCK TABLE
在事務後期執行仍然會阻止併發寫入 — 但它不能確保事務讀取的內容對應於最新的已提交值。
如果此型別的事務將要更改表中的資料,則應使用 SHARE ROW EXCLUSIVE
鎖模式而不是 SHARE
模式。這確保一次只有一個此類事務執行。沒有這一點,可能會發生死鎖:兩個事務可能都獲取 SHARE
模式,然後無法獲取 ROW EXCLUSIVE
模式來實際執行其更新。(請注意,事務自身的鎖永遠不會衝突,因此事務可以在持有 SHARE
模式時獲取 ROW EXCLUSIVE
模式 — 但不能在任何人持有 SHARE
模式時獲取。)為避免死鎖,請確保所有事務以相同的順序在相同物件上獲取鎖,並且如果一個物件涉及多種鎖模式,則事務應始終首先獲取最嚴格的模式。
有關鎖模式和鎖定策略的更多資訊,請參閱 第 13.3 節。
name
要鎖定的現有表的名稱(可選模式限定)。如果在此表名前指定 ONLY
,則僅鎖定該表。如果未指定 ONLY
,則鎖定該表及其所有後代表(如果有)。可以選擇在表名後指定 *
來顯式表示包括後代表。
命令 LOCK TABLE a, b;
等同於 LOCK TABLE a; LOCK TABLE b;
。表按 LOCK TABLE
命令中指定的順序逐個鎖定。
lockmode
鎖模式指定此鎖與之衝突的鎖。鎖模式在 第 13.3 節 中描述。
如果未指定鎖模式,則使用最嚴格的模式 ACCESS EXCLUSIVE
。
NOWAIT
指定 LOCK TABLE
不應等待任何衝突的鎖被釋放:如果指定的鎖無法立即獲取而不等待,則事務中止。
使用者必須對指定的 lockmode
具有許可權才能鎖定表。如果使用者對該表具有 MAINTAIN
、UPDATE
、DELETE
或 TRUNCATE
許可權,則允許任何 lockmode
。如果使用者對該表具有 INSERT
許可權,則允許 ROW EXCLUSIVE MODE
(或更少衝突的模式,如 第 13.3 節 中所述)。如果使用者對該表具有 SELECT
許可權,則允許 ACCESS SHARE MODE
。
執行檢視鎖定的使用者必須對檢視具有相應的許可權。此外,預設情況下,檢視所有者必須對底層基本關係具有相關許可權,而執行鎖定的使用者不需要對底層基本關係具有任何許可權。但是,如果檢視的 security_invoker
設定為 true
(參見 CREATE VIEW
),則執行鎖定的使用者而不是檢視所有者必須對底層基本關係具有相關許可權。
LOCK TABLE
在事務塊外部是無用的:鎖只會保留到語句完成。因此,如果 LOCK
在事務塊外部使用,PostgreSQL 會報告錯誤。使用 BEGIN
和 COMMIT
(或 ROLLBACK
)來定義一個事務塊。
LOCK TABLE
只處理表級鎖,因此涉及 ROW
的模式名稱都帶有誤導性。這些模式名稱通常應理解為表示使用者將在鎖定的表內獲取行級鎖的意圖。此外,ROW EXCLUSIVE
模式是一種可共享的表鎖。請記住,對於 LOCK TABLE
而言,所有鎖模式的語義都是相同的,僅在哪些模式與哪些模式衝突的規則上有所不同。有關如何獲取實際行級鎖的資訊,請參閱 第 13.3.2 節 和 鎖定子句 中的 SELECT 文件。
在將要向外鍵表執行插入操作時,獲取主鍵表的 SHARE
鎖
BEGIN WORK; LOCK TABLE films IN SHARE MODE; SELECT id FROM films WHERE name = 'Star Wars: Episode I - The Phantom Menace'; -- Do ROLLBACK if record was not returned INSERT INTO films_user_comments VALUES (_id_, 'GREAT! I was waiting for it for so long!'); COMMIT WORK;
在將要執行刪除操作時,獲取主鍵表的 SHARE ROW EXCLUSIVE
鎖
BEGIN WORK; LOCK TABLE films IN SHARE ROW EXCLUSIVE MODE; DELETE FROM films_user_comments WHERE id IN (SELECT id FROM films WHERE rating < 5); DELETE FROM films WHERE rating < 5; COMMIT WORK;
SQL 標準中沒有 LOCK TABLE
,它使用 SET TRANSACTION
來指定事務的併發級別。PostgreSQL 也支援這一點;有關詳細資訊,請參閱 SET TRANSACTION。
除了 ACCESS SHARE
、ACCESS EXCLUSIVE
和 SHARE UPDATE EXCLUSIVE
鎖模式外,PostgreSQL 鎖模式和 LOCK TABLE
語法與 Oracle 中的語法相容。
如果您在文件中發現任何不正確、與您對特定功能的體驗不符或需要進一步說明的內容,請使用 此表單 報告文件問題。