PostgreSQL 到底有没有PAGE 锁 与 Advisory Locks

2020-05-25 00:00:00 数据库 都是 方式 例子 其他的


事情的起因是,之前写了一篇比较MYSQL 和 PG 的MVCC的文字,其中提到PG 没有 PAGE LOCK,有同学指正,提出PG是有 PAGE LOCK 的。


到底PG 有没有 PAGE LOCK 个人觉得的搞搞清楚,并且有错必改,也感谢给我指正的 “灿” 同学。


1 首先直观的方式就是官方文档

https://www.postgresql.org/docs/12/explicit-locking.html

但问题可能有同学提出在PG 9.3 以及以前的版本中并未看到,单独列出的 page level locks 这个单独的项目,但实际仔细的查找之前的版本的 page level locks 是在 Row-level locks 这个项目中,并且从早期的9.x写到现在的PG12 都是一句话带过

和有些数据库对PAGE LOCKS 的详细描述和功能性的描述(对比SQL SERVER),PG 对PAGE LOCKS 描述有点简单。


 既然想从文档中探究秘密的想法无法达成,只能看看源代码里面能不能有点收获 lock.h 文件中有相关锁的定义和处理的方式,打开文件

相关的使用locktage_page 锁的例子,可以在src/backend/access/gin/ginfast.c:               

LockPage(index,GIN_METAPAGE_BLKNO, ExclusiveLock)

中找到相关使用locktage_page 的程序段

应该还有其他的PAGE 锁,但限于时间和经历的限制,没有继续再找,如果还有其他的还请高手不吝赐教,感谢。


实际上在上一篇中给出一句PG 没有PAGE 锁,这个的确是不正确的,这里也说说我理解的PAGE 锁的含义是什么,为什么说了那样一句话。

先用一个图来看一下SQL SERVER 的PAGE LOCK 和 ROW LOCK  , TABLE LOCK 的关系

SQL SERVER 与其他数据库不一样的地方,在于资源的动态锁定,也就是他可能一开始使用了ROW 锁, 但由于后期整体操作的复杂度提高,直接将ROW 锁升级为页锁, 而其他的数据库目前我是没有听到有确认的一种叫法 Lock escalation.

另外SQL SERVER 在行锁和页锁中,是可以将其进行 enabled 和 disabled的,这点相对于其他数据库的方面还是灵活的。

所以可能如果从之前理解的一些页锁的概念和使用的方式来说, PG的页锁是不可随意控制,从应用程序developer角度也无需深刻理解的。

反观SQL SERVER 如果程序员在处理一些应用的过程中,建议还是考虑一下锁升级的问题,因为锁升级必然导致更多的锁冲突。


回过头来在看PG 的Advisory Locks ,下面通过两个例子来说明advisory locks 的作用。因为其他的数据库没有这样的设定(如果有还请指正,至少没MYSQL , SQL SERVER 是没有的)


1  SESSION 下面我们找两个SESSION   SESSION 1  SESSION 2 


SESSION 1

SESSION 2 


从上面的例子中可以领会到Advisory Locks 具体的功能,首先在MVCC 无法解决应用关于数据处理的次序性和数据的性的情况下通过Advisory Locks在应用程序中使用,通过SESSION 级别 或者 transcation 级别通过Advisory Locks来达到某种特殊的需求。


如上面的例子中,SESSION 1  插入数据, 但SESSION 2 需要删除 ID =1 的数据,但问题是怎么判断 SESSION1中的数据表中已经存在了 数据,如果是其他的数据库可能需要其他手段,例如在表中设置状态位的逻辑方式来不断进行判断,但实际上这就产生了锁,任何对数据库中的表的操作都会产生锁,这就造成了数据库的资源的争夺,在频繁的获取状态的情况或修改状态的情况下,就会产生BLOCK 甚至可能会有死锁。PG 在这方面对于应用是友好的通过Advisory Locks  不会物理的对数据库产生任何的资源消耗,而是在应用程序中,设置Advisory Locks 来在不同的SESSION 或者 TRANSACTION 中判断相互的状态,而采取相对的操作。


下面是一个事务的例子,并发的时候transaction 2,无法获知到底transaction1到底是不是将ID =4 插入到 TEST 表中,所以通过pg_try_advisory_xact_lock 来阻止 transactoin 2 程序出错,这也是一种使用advisory_lock的方式。


transaction 1

transaction 2


之所以之前没有看到有人提到这个所,估计是运维DBA 不关心,因为这与软件的设计有关,至少要懂得业务的逻辑与程序的设计, 而程序员目前能完全掌握PG的人,估计比DBA 还少,大多都是浅尝, 所以学习PG 必须深挖"三不管", 让其为程序设计提供更多的服务方式和使用方式.


相关文章