PostgreSQL的官方文档中,说明了PG中的锁分成了八个等级:
- AccessShareLock
- RowShareLock
- RowExclusiveLock
- ShareUpdateExclusiveLock
- ShareLock
- ShareRowExclusiveLock
- ExclusiveLock
- AccessExclusiveLock
这些锁的相容性呢,在文档中也给出了一个二维表格清晰的展示:
文档地址: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进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。