暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

浅谈PostgreSQL中的锁 - 1

原创 SHX 2022-05-27
2091

PostgreSQL的官方文档中,说明了PG中的锁分成了八个等级:

  • AccessShareLock
  • RowShareLock
  • RowExclusiveLock
  • ShareUpdateExclusiveLock
  • ShareLock
  • ShareRowExclusiveLock
  • ExclusiveLock
  • AccessExclusiveLock

这些锁的相容性呢,在文档中也给出了一个二维表格清晰的展示:
Image.png

文档地址:http://www.postgres.cn/docs/12/explicit-locking.html

那其实在 lock 的头文件中,以上八种锁分别声明了 1-8 共8个值;另外还定义了一个 NoLock 0 ,但是不作为锁的一个模式,只是作为一个标识值,来表示不去获取锁。
src/include/storage/lockdefs.h

#define NoLock                  0  
#define AccessShareLock         1   /\* SELECT \*/  
#define RowShareLock            2   /\* SELECT FOR UPDATE/FOR SHARE \*/  
#define RowExclusiveLock        3   /\* INSERT, UPDATE, DELETE \*/  
#define ShareUpdateExclusiveLock 4  /\* VACUUM (non-FULL),ANALYZE, CREATE INDEX  
                                     \* CONCURRENTLY \*/  
#define ShareLock               5   /\* CREATE INDEX (WITHOUT CONCURRENTLY) \*/  
#define ShareRowExclusiveLock   6   /\* like EXCLUSIVE MODE, but allows ROW  
                                     \* SHARE \*/  
#define ExclusiveLock           7   /\* blocks ROW SHARE/SELECT...FOR UPDATE \*/  
#define AccessExclusiveLock     8   /\* ALTER TABLE, DROP TABLE, VACUUM FULL,  
                                     \* and unqualified LOCK TABLE \*/  
#define MaxLockMode             8  
复制

从上面代码的注释可以看出数据库中哪些操作会申请这些锁,我也根据文档中的描述,制作了一个表格,如下:

锁模式 操作
ACCESS SHARE SELECT
ROW SHARE SELECT FOR UPDATE \ SELECT FOR SHARE
ROW EXCLUSIVE UPDATE \ DELETE \ INSERT
SHARE UPDATE EXCLUSIVE ACUUM \ ANALYZE \ CREATE INDEX CONCURRENTLY \ REINDEX CONCURRENTLY \ CREATE STATISTICS \ ALTER INDEX(部分) \ ALTER TABLE(部分)SHARECREATE INDEX(部分)
SHARE ROW EXCLUSIVE CREATE TRIGGER \ ALTER TABLE(部分)
EXCLUSIVE REFRESH MATERIALIZED VIEW CONCURRENTLY
ACCESS EXCLUSIVE ALTER TABLE \ DROP TABLE \ TRUNCATE \ REINDEX \ CLUSTER \ VACUUM FULL \REFRESH MATERIALIZED VIEW

数据库中操作任何relation,都会传一个锁模式的参数,去做并发控制。

relation_open(Oid relationId, LOCKMODE lockmode) {...}  
relation_openrv(const RangeVar *relation, LOCKMODE lockmode) {...}  
relation_openrv_extended(const RangeVar *relation, LOCKMODE lockmode,  
                         bool missing_ok) {...}  
relation_close(Relation relation, LOCKMODE lockmode) {...}  
复制

所以在平常一些程序设计的时候,要尽量避免出现大量的锁争用情况。

如果安装数据库后想去探索锁的相互阻塞关系,可以通过 lock 命令去获取对象上的锁,然后利用 pg_lock, pg_stat_activity 等视图查看锁的状态信息,通过 pg_blocking_pids(pid) 接口函数去查看锁的阻塞队列信息。

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论