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

postgresql中的咨询锁(advisory lock)

原创 kerosene 2022-06-15
1892

咨询锁(advisory lock),有的地方翻译为顾问锁,作为Postgresql中一种特有的锁,关于对其介绍,仅从咨询锁的描述性定义来看,一开始还真的没明白这个咨询锁是干什么的。

暂时抛开咨询锁的概念,先说数据库中传统的锁机制。
默认情况下的事务性锁,读/写会自动加锁,读/写完成后会自动解锁(加解锁机制在细节上复杂),这是一种隐式的锁机制,Postgresql也不例外。
对于加锁后的并发控制,也就是默认的写不阻塞读,是通过MVCC解决的,这种锁完全不需要人为干预。
相对于隐式锁机制和MVCC并发控制机制,咨询锁可以认为是一种显式锁,需要人为地控制,这类锁需要显式的申请和释放,在使用这类锁的时候,可以自行控制读写的排他性。

什么场景下使用显式锁?
比如想实现写阻塞读,或者读阻塞读的场景,因为默认的隐式锁加上MVCC机制,是做不到的。
实际业务类型需求的场景也很多:一个经典的问题,并发情况下,对唯一键的存性判断,然后决定存在则更新,不存在则插入这种逻辑,就需要咨询锁,默认的MVCC下是做不到的,当然也不是说咨询锁只能做这个事儿。
再举个例子:多线程编程中的线程共享变量,在读写共享变量时需要线程锁做控制(比如python的lock.acquire()),完成之后释放锁,咨询锁就有点这个味道(当然不完全相同),这些都是隐式锁无法完成的。

 

查看问官方文档的时候还是吓了一跳,Postgresql有这么多类型的咨询锁。

Table 9-73. Advisory Lock Functions

NameReturn TypeDescription
pg_advisory_lock(key bigint)voidObtain exclusive session level advisory lock
pg_advisory_lock(key1 intkey2 int)voidObtain exclusive session level advisory lock
pg_advisory_lock_shared(key bigint)voidObtain shared session level advisory lock
pg_advisory_lock_shared(key1 intkey2 int)voidObtain shared session level advisory lock
pg_advisory_unlock(key bigint)booleanRelease an exclusive session level advisory lock
pg_advisory_unlock(key1 intkey2 int)booleanRelease an exclusive session level advisory lock
pg_advisory_unlock_all()voidRelease all session level advisory locks held by the current session
pg_advisory_unlock_shared(key bigint)booleanRelease a shared session level advisory lock
pg_advisory_unlock_shared(key1 intkey2 int)booleanRelease a shared session level advisory lock
pg_advisory_xact_lock(key bigint)voidObtain exclusive transaction level advisory lock
pg_advisory_xact_lock(key1 intkey2 int)voidObtain exclusive transaction level advisory lock
pg_advisory_xact_lock_shared(key bigint)voidObtain shared transaction level advisory lock
pg_advisory_xact_lock_shared(key1 intkey2 int)voidObtain shared transaction level advisory lock
pg_try_advisory_lock(key bigint)booleanObtain exclusive session level advisory lock if available
pg_try_advisory_lock(key1 intkey2 int)booleanObtain exclusive session level advisory lock if available
pg_try_advisory_lock_shared(key bigint)booleanObtain shared session level advisory lock if available
pg_try_advisory_lock_shared(key1 intkey2 int)booleanObtain shared session level advisory lock if available
pg_try_advisory_xact_lock(key bigint)booleanObtain exclusive transaction level advisory lock if available
pg_try_advisory_xact_lock(key1 intkey2 int)booleanObtain exclusive transaction level advisory lock if available
pg_try_advisory_xact_lock_shared(key bigint)booleanObtain shared transaction level advisory lock if available
pg_try_advisory_xact_lock_shared(key1 intkey2 int)booleanObtain shared transaction level advisory lock if available

其实细看下去,并不复杂,按照“申请/释放,生效范围”,锁类型,参数个数,等待行为,这个咨询锁从几个维度分类之后,还是比较清晰的。
所有的咨询锁函数都是这几个维度的不同组合,只要弄清楚这些锁的不同维度,上面表格中洋洋洒洒的数十个锁函数,加上备注,理解起来还是比较容易的。

 

如下对生效范围,锁类型,申请/释放,参数个数,等待行为逐一解释:

  • 1,申请/释放:有申请就有释放,Session级别的锁需要显式释放,随着连接的关闭自动释放;事务级别的锁也需要显式释放,或者会随着事务的结束(提交或者回滚)一并释放
  • 2,锁类型:共享锁和排它锁,比如pg_advisory_lock是排它锁,pg_advisory_lock_shared是共享锁
  • 3,生效范围:Session级的或者事务级的,很好理解,比如pg_advisory_lock是添加Session级的排它锁,pg_advisory_xact_lock是申请事务级排它锁
  • 4,参数个数,这个看概念是有点蒙的,有的锁函数是1个参数,有的是2个参数,一个参数的情况下,锁是库级别的,举个例子就很容易理解了


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

评论