鎖類型
參考文檔: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)