咨询锁(advisory lock),有的地方翻译为顾问锁,作为Postgresql中一种特有的锁,关于对其介绍,仅从咨询锁的描述性定义来看,一开始还真的没明白这个咨询锁是干什么的。
暂时抛开咨询锁的概念,先说数据库中传统的锁机制。
默认情况下的事务性锁,读/写会自动加锁,读/写完成后会自动解锁(加解锁机制在细节上复杂),这是一种隐式的锁机制,Postgresql也不例外。
对于加锁后的并发控制,也就是默认的写不阻塞读,是通过MVCC解决的,这种锁完全不需要人为干预。
相对于隐式锁机制和MVCC并发控制机制,咨询锁可以认为是一种显式锁,需要人为地控制,这类锁需要显式的申请和释放,在使用这类锁的时候,可以自行控制读写的排他性。
什么场景下使用显式锁?
比如想实现写阻塞读,或者读阻塞读的场景,因为默认的隐式锁加上MVCC机制,是做不到的。
实际业务类型需求的场景也很多:一个经典的问题,并发情况下,对唯一键的存性判断,然后决定存在则更新,不存在则插入这种逻辑,就需要咨询锁,默认的MVCC下是做不到的,当然也不是说咨询锁只能做这个事儿。
再举个例子:多线程编程中的线程共享变量,在读写共享变量时需要线程锁做控制(比如python的lock.acquire()),完成之后释放锁,咨询锁就有点这个味道(当然不完全相同),这些都是隐式锁无法完成的。
查看问官方文档的时候还是吓了一跳,Postgresql有这么多类型的咨询锁。
Table 9-73. Advisory Lock Functions
| Name | Return Type | Description |
|---|---|---|
pg_advisory_lock(key bigint) | void | Obtain exclusive session level advisory lock |
pg_advisory_lock(key1 int, key2 int) | void | Obtain exclusive session level advisory lock |
pg_advisory_lock_shared(key bigint) | void | Obtain shared session level advisory lock |
pg_advisory_lock_shared(key1 int, key2 int) | void | Obtain shared session level advisory lock |
pg_advisory_unlock(key bigint) | boolean | Release an exclusive session level advisory lock |
pg_advisory_unlock(key1 int, key2 int) | boolean | Release an exclusive session level advisory lock |
pg_advisory_unlock_all() | void | Release all session level advisory locks held by the current session |
pg_advisory_unlock_shared(key bigint) | boolean | Release a shared session level advisory lock |
pg_advisory_unlock_shared(key1 int, key2 int) | boolean | Release a shared session level advisory lock |
pg_advisory_xact_lock(key bigint) | void | Obtain exclusive transaction level advisory lock |
pg_advisory_xact_lock(key1 int, key2 int) | void | Obtain exclusive transaction level advisory lock |
pg_advisory_xact_lock_shared(key bigint) | void | Obtain shared transaction level advisory lock |
pg_advisory_xact_lock_shared(key1 int, key2 int) | void | Obtain shared transaction level advisory lock |
pg_try_advisory_lock(key bigint) | boolean | Obtain exclusive session level advisory lock if available |
pg_try_advisory_lock(key1 int, key2 int) | boolean | Obtain exclusive session level advisory lock if available |
pg_try_advisory_lock_shared(key bigint) | boolean | Obtain shared session level advisory lock if available |
pg_try_advisory_lock_shared(key1 int, key2 int) | boolean | Obtain shared session level advisory lock if available |
pg_try_advisory_xact_lock(key bigint) | boolean | Obtain exclusive transaction level advisory lock if available |
pg_try_advisory_xact_lock(key1 int, key2 int) | boolean | Obtain exclusive transaction level advisory lock if available |
pg_try_advisory_xact_lock_shared(key bigint) | boolean | Obtain shared transaction level advisory lock if available |
pg_try_advisory_xact_lock_shared(key1 int, key2 int) | boolean | Obtain 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个参数,一个参数的情况下,锁是库级别的,举个例子就很容易理解了




