了解鎖定
多版本並行控制 (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;