PostgreSQL咨询锁(advisory lock)
一、什么是咨询锁?
PostgreSQL 支持创建咨询锁(advisory lock),该锁与数据库本身没有关系,其含义由应用来定义,咨询锁能够让 PostgreSQL 变成一个锁服务提供中心,为应用对一些非数据库资源并发访问提供控制。当然,也可以通过 select * from tb where id=xxx for update 来实现同样的功能,但是咨询锁因为与具体的数据没有关系,能够提供更好的性能。
PostgreSQL 咨询锁能够实现很多分布式系统中类似 Zookeeper 的锁服务,如在分布式系统中,多台服务器需要竞争,从而使自己成为 master,就可以通过竞争咨询锁来达成,谁得到咨询锁,谁就成为 master。
咨询锁支持会话级别和事务级别,会话级别的咨询锁,在会话结束时会自动释放,事务级别的咨询锁,在事务结束时自动释放。
二、咨询锁相关函数
咨询锁用一个 64 bit 的数字或者两个 32 bit 的数字来表示,并提供了一些函数来实现加锁和释放锁的操作,函数如下:
函数名称 | 返回类型 | 描述 |
---|---|---|
pg_advisory_lock(key bigint) | void | session级别排他锁 |
pg_advisory_lock(key1 int, key2 int) | void | session级别排他锁 |
pg_advisory_lock_shared(key bigint) | void | session级别共享锁 |
pg_advisory_lock_shared(key1 int, key2 int) | void | session级别共享锁 |
pg_advisory_unlock(key bigint) | boolean | 释放session级别排他锁 |
pg_advisory_unlock(key1 int, key2 int) | boolean | 释放session级别排他锁 |
pg_advisory_unlock_all() | void | 释放本session持有的所有session级别的锁 |
pg_advisory_unlock_shared(key bigint) | boolean | 释放session级别共享锁 |
pg_advisory_unlock_shared(key1 int, key2 int) | boolean | 释放session级别共享锁 |
pg_advisory_xact_lock(key bigint) | void | 获取事务级别排他锁 |
pg_advisory_xact_lock(key1 int, key2 int) | void | 获取事务级别排他锁 |
pg_advisory_xact_lock_shared(key bigint) | void | 获取事务级别共享锁 |
pg_advisory_xact_lock_shared(key1 int, key2 int) | void | 获取事务级别共享锁 |
pg_try_advisory_lock(key bigint) | boolean | 试图获取session级别排他锁,成功返回true,否则返回false |
pg_try_advisory_lock(key1 int, key2 int) | boolean | 试图获取session级别排他锁,成功返回true,否则返回false |
pg_try_advisory_lock_shared(key bigint) | boolean | 试图获取session级别共享锁,成功返回true,否则返回false |
pg_try_advisory_lock_shared(key1 int, key2 int) | boolean | 试图获取session级别共享锁,成功返回true,否则返回false |
pg_try_advisory_xact_lock(key bigint) | boolean | 试图获取事务级别排他锁,成功返回true,否则返回false |
pg_try_advisory_xact_lock(key1 int, key2 int) | boolean | 试图获取事务级别排他锁,成功返回true,否则返回false |
pg_try_advisory_xact_lock_shared(key bigint) | boolean | 试图获取事务级别共享锁,成功返回true,否则返回false |
pg_try_advisory_xact_lock_shared(key1 int, key2 int) | boolean | 试图获取事务级别共享锁,成功返回true,否则返回false |
根据函数名称中的关键字,就能大概判断出函数的功能:
- lock 为加锁。
- unlock 释放锁。
- xact 为事务级别的咨询锁,不包含 xact 为 session 级别的咨询锁。事务级别的咨询锁只有加锁函数,没有 unlock 函数,因为事务锁在事务结束后自动释放。
- try 尝试加锁,不管是否能获得锁,都立即返回,不会一直等待。
- 根据参数类型分为不同的函数,int 表示 32 位数字,bigint 表示 64 位数字。
三、咨询锁使用示例
以下展示了两个会话,获取 session 级排他咨询锁的示例:
session1:
pg=# select pg_advisory_lock(1); # session1 加锁
pg_advisory_lock
------------------
(1 row)
session2:
pg=# select pg_advisory_lock(1); # session2 阻塞
session1:
pg=# select pg_advisory_unlock(1); # session1 释放锁
pg_advisory_unlock
--------------------
t
(1 row)
session2:
pg=# select pg_advisory_lock(1); # session2 获得锁
pg_advisory_lock
------------------
(1 row)