Postgres10高性能開發(6)鎖及其檢查

鎖類型

參考文檔:https://www.postgresql.org/docs/10/explicit-locking.html

表級鎖

鎖名稱 引發操作
ACCESS SHARE 訪問共享鎖 SELECT
任何讀取不修改表的查詢都將獲取本鎖
ROW SHARE 行共享鎖 SELECT FOR UPDATE
SELECT FOR SHARE
ROW EXCLUSIVE 行排他鎖 UPDATE
DELETE
INSERT
SHARE UPDATE EXCLUSIVE 共享更新排他鎖 VACUUM(不含FULL)ANALYZE
CREATE INDEX CONCURRENTLY
CREATE STATISTICS
部分ALTER TABLE
SHARE 共享鎖 CREATE INDEX(無CONCURRENTLY)
SHARE ROW EXCLUSIVE 共享行級排它鎖 CREATE COLLATION
CREATE TRIGGER
部分ALTER TABLE
EXCLUSIVE 排它鎖 REFRESH MATERIALIZED VIEW CONCURRENTLY
ACCESS EXCLUSIVE 訪問排他鎖 DROP TABLE
TRUNCATE
REINDEX
CLUSTER
VACUUM FULL
REFRESH MATERIALIZED VIEW (不含 CONCURRENTLY)
Requested Lock Mode Current Lock Mode
ACCESS SHARE ROW SHARE ROW EXCLUSIVE SHARE UPDATE EXCLUSIVE SHARE SHARE ROW EXCLUSIVE EXCLUSIVE ACCESS EXCLUSIVE
ACCESS SHARE               X
ROW SHARE             X X
ROW EXCLUSIVE         X X X X
SHARE UPDATE EXCLUSIVE       X X X X X
SHARE     X X   X X X
SHARE ROW EXCLUSIVE     X X X X X X
EXCLUSIVE   X X X X X X X
ACCESS EXCLUSIVE X X X X X X X X

行級鎖

鎖定查找到行,阻止對行進行某些操作

阻止操作
FOR UPDATE UPDATE
DELETE
SELECT FOR UPDATE
SELECT FOR NO KEY UPDATE
SELECT FOR SHARE
SELECT FOR KEY SHARE
FOR NO KEY UPDATE UPDATE
DELETE
SELECT FOR UPDATE
SELECT FOR NO KEY UPDATE
SELECT FOR SHARE
FOR SHARE UPDATE
DELETE
SELECT FOR UPDATE
SELECT FOR NO KEY UPDATE
FOR KEY SHARE UPDATE
DELETE
SELECT FOR UPDATE
Requested Lock Mode Current Lock Mode
FOR KEY SHARE FOR SHARE FOR NO KEY UPDATE FOR UPDATE
FOR KEY SHARE       X
FOR SHARE     X X
FOR NO KEY UPDATE   X X X
FOR UPDATE X X X X

檢查和處理鎖

參考文檔:https://www.postgresql.org/docs/10/view-pg-locks.html

死鎖

如果數據庫發現死鎖,數據庫將自動發現並終止死鎖

pg_locks

pg_locks視圖記錄當前進程的鎖定情況,主要字段包括

  • locktype:鎖定類型,包括 relation(表), extend, page, tuple(元組), transactionid(事物ID), virtualxid, object, userlock, or advisory
  • database:鎖所在數據庫ID,關聯到 pg_database.oid
  • relation:鎖所在的表ID,關聯到pg_class.oid
  • pid:持有鎖或等待鎖的進程ID
  • mode:持有或等待的鎖名稱
  • granted:True表示數已持有,false表示在等待持有

查找當前的鎖

select l.mode,granted,l.locktype,l.pid,query,query_start,db.datname,relname,l.*
from pg_locks l LEFT JOIN pg_stat_activity a on a.pid = l.pid
LEFT JOIN pg_database db on oid = database
LEFT JOIN pg_class on oid = relation
where 1=1
--and l.pid=20139
--and database=(select oid from pg_database where datname='test')
--and relation=(select oid from pg_class where relname='report_user')

排查鎖定方法

首先查找一直在等待的鎖

select l.mode,granted,l.locktype,l.pid,query,query_start,db.datname,relname,l.*
from pg_locks l LEFT JOIN pg_stat_activity a on a.pid = l.pid
LEFT JOIN pg_database db on oid = database
LEFT JOIN pg_class on oid = relation
where granted = false

在根據鎖定類型,鎖定對象查找當前持有這個鎖的PID及SQL,例如

select l.mode,granted,l.locktype,l.pid,query,query_start,db.datname,relname,l.*
from pg_locks l LEFT JOIN pg_stat_activity a on a.pid = l.pid
LEFT JOIN pg_database db on oid = database
LEFT JOIN pg_class on oid = relation
where transactionid=81401737

判斷已獲取的鎖是否與當前鎖衝突,如果衝突,可以使用其PID停止該數據庫連接以釋放鎖
例如:PID爲31292

select pg_terminate_backend(31292)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章