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)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章