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
陳述式。REPEATABLE READ
或 SERIALIZABLE
交易的資料視窗將在其第一個 SELECT
或資料修改陳述式開始時凍結。交易中稍後的 LOCK TABLE
仍然會防止並行寫入 — 但它不能確保交易讀取的內容與最新的已提交值相對應。
如果此類型的交易將變更資料表中的資料,則應使用 SHARE ROW EXCLUSIVE
鎖定模式,而不是 SHARE
模式。這可確保一次只執行一個此類型的交易。如果沒有這個,可能會發生死鎖:兩個交易可能都會取得 SHARE
模式,然後無法取得 ROW EXCLUSIVE
模式來實際執行其更新。(請注意,交易自己的鎖定永遠不會衝突,因此交易可以在持有 SHARE
模式時取得 ROW EXCLUSIVE
模式 — 但如果其他人持有 SHARE
模式則不行。)為了避免死鎖,請確保所有交易以相同的順序取得相同物件的鎖定,並且如果單個物件涉及多個鎖定模式,則交易應始終先取得限制最多的模式。
有關鎖定模式和鎖定策略的更多資訊,請參閱 第 13.3 節。
name
要鎖定的現有資料表的名稱(選擇性地以 schema 限定)。如果在資料表名稱之前指定 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 中存在的鎖定模式和語法相容。
如果您在文件中看到任何不正確、與您使用特定功能的經驗不符或需要進一步澄清的內容,請使用此表單來報告文件問題。