锁类型
参考文档: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)