了解鎖定

已完成

多版本並行控制 (MVCC) 提供適用於大部分案例的適當並行設定。 不過,如果應用程式需要特定的鎖定,以確切控制哪些數據列受到影響,且具有特定鎖定層級,則明確鎖定模式會啟用此精細的控制。

在適用於 PostgreSQL 的 Azure 資料庫中,有三種類型的明確鎖定、數據表層級鎖定、數據列層級鎖定和頁面層級鎖定。 初始交易會要求鎖定,如果接受,則要求的鎖定會成為現有的鎖定。 如有另一筆交易嘗試解除對相同資料的鎖定,則若鎖定與原始交易不衝突,隨即會授與鎖定。

例如,兩個交易可以使用SELECT語句同時查詢相同的數據。 這些要求會使用 ACCESS SHARE 鎖定,兩筆交易皆獲允許。 在另一個案例中,一個交易會使用 SELECT 語句和 ACCESS SHARE 鎖定來查詢數據,但同時另一個交易會嘗試卸除相同的數據表。 卸除資料表需要使用此案例中不被授與的 ACCESS EXCLUSIVE 鎖定。

資料表層級鎖定

資料表層級鎖定會取得整份資料表的鎖定,即使名稱中有 ROW 也一樣。 如果您正在修改資料表本身,或者鎖定整份資料表比解除許多資料列層級鎖定更有效率,您可能需要鎖定整份資料表。

適用於 PostgreSQL 的 Azure 資料庫中有八種類型的數據表層級鎖定,而取得這些鎖定類型的 SQL 命令如下:

鎖定模式 取得者
ACCESS SHARE SELECT 命令
ROW SHARE SELECT FOR UPDATE 和 SELECT FOR SHARE 命令
ROW EXCLUSIVE UPDATE、DELETE 和 INSERT 命令
獨家更新分享 ANALYZE、CREATE INDEX CONCURRENTLY、CREATE STATISTICS、COMMENT ON、REINDEX CONCURRENTLY 命令,部分 ALTER INDEX 和 ALTER TABLE 命令,以及 VACUUM (不是 FULL)
SHARE 建立索引(非並行)命令
SHARE ROW EXCLUSIVE CREATE TRIGGER 命令和部分 ALTER TABLE 命令
EXCLUSIVE REFRESH MATERIALIZED VIEW CONCURRENTLY 命令
專屬訪問權限 DROP TABLE、REINDEX、TRUNCATE、CLUSTER、REFRESH MATERIALIZED VIEW (不是 CONCURRENTLY) 命令,大部分的 ALTER INDEX 和 ALTER TABLE 命令,以及 VACUUM FULL

每種現有的鎖定類型都會封鎖其他要求的鎖定。 下表列出哪些鎖定會封鎖其他鎖定:

-- 現有的 ACCESS SHARE 現有的 ROW SHARE 現有的 ROW EXCLUSIVE 現有的 SHARE UPDATE EXCLUSIVE 現有的 SHARE 現有的 SHARE ROW EXCL 現有的 EXCLUSIVE 現有的 ACCESS EXCLUSIVE
要求的 ACCESS SHARE 已封鎖
要求的 ROW SHARE 已封鎖 已封鎖
要求的 ROW EXCLUSIVE 已封鎖 已封鎖 已封鎖 已封鎖
要求的 SHARE UPDATE EXCLUSIVE 已封鎖 已封鎖 已封鎖 已封鎖 已封鎖
要求的 SHARE 已封鎖 已封鎖 已封鎖 已封鎖 已封鎖
要求的 SHARE ROW EXCLUSIVE 已封鎖 已封鎖 已封鎖 已封鎖 已封鎖 已封鎖
要求的 EXCLUSIVE 已封鎖 已封鎖 已封鎖 已封鎖 已封鎖 已封鎖 已封鎖
要求的 ACCESS EXCLUSIVE 已封鎖 已封鎖 已封鎖 已封鎖 已封鎖 已封鎖 已封鎖 已封鎖

資料列層級鎖定

數據列層級鎖定更細微,只會影響另一個存取相同數據列的交易。 這個鎖定類型可改善並行,但取得和卸除許多鎖定會對效能造成負面影響。 PostgreSQL 會自動取得列級鎖,而不需要手動套用。

適用於 PostgreSQL 的 Azure 資料庫中有四種類型的資料列層級鎖定,將隨需要封鎖的其他鎖定類型而取得:

-- 現有的 FOR KEY SHARE 現有的 FOR SHARE 現有的 FOR NO KEY UPDATE 現有的 FOR UPDATE
要求的 FOR KEY SHARE 已封鎖
要求的 FOR SHARE 已封鎖 已封鎖
要求的 FOR NO KEY UPDATE 已封鎖 已封鎖 已封鎖
要求進行更新 已封鎖 已封鎖 已封鎖 已封鎖

頁面層級鎖定

頁面層級鎖定會影響一個資料頁,通常由多個列組成。 雖然 PostgreSQL 行程使用頁面層級鎖定,但應用程式開發人員通常不需要這種類型的鎖定。

手動套用鎖定及檢視目前的鎖定

若要手動套用數據表層級鎖定,您可以使用LOCK命令搭配必要的鎖定模式。 LOCK 命令必須位於交易內,且交易完成時會釋放鎖定。 例如:

BEGIN TRANSACTION;
LOCK TABLE humanresources.department IN ROW EXCLUSIVE MODE;
COMMIT;

若要檢視目前保留在資料庫的鎖定,請使用 pg_locks。 例如,使用下列命令可以檢視目前所有的鎖定:

SELECT * FROM pg_locks;