绑定完请刷新页面
取消
刷新

分享好友

×
取消 复制
PG的BUFFER相关锁
2022-12-01 17:19:50

昨天刚刚下飞机就接到电话说一个长辈去世,今天一早坐高铁回老家参加丧礼。所以这篇前两天写了个头的文章今天是在高铁上完成的,有些实验不方便做,就只能简化了。

前两天一个朋友说PG的热块冲突比Oracle更容易产生,并会产生比较严重的性能问题,特别是当系统中的一些大型的热表存在大量UPDATE操作的时候。确实PG的ASTORE机制使用多个版本的TUPLE来保存某一行的历史版本,这种机制导致了PG的SHARED BUFFERS的锁会比较复杂。和朋友讨论问题后,我根据以前学习过的一些关于PG BUFFER的知识,画了一个思维导图。

PG的BUFFER 居然和三种锁有关,一种是SPINLOCK,用于管理BUFFER的空闲链的,如果要分配空闲缓冲区,则需要通过一个SPINLOCK(Buffer Strategy Lock)来获得。另外两类异类是我们比较容易理解的用于保护PG内存结构的锁LWLOCK。后异类就比较令人费解了,如果我们看PG的等待事件,里面有一类独特的分类。

这类等待事件称为BufferPin,而这个等待事件大类里面只有一种等待事件,BufferPIN。这些锁之间都是什么关系呢?我们可以看上面的思维导图。


比如我们模拟一个BUFFER的一生,首先当要访问某个PG PAGE的时候,先要从FREE的BUFFER中找到一个,此时需要一个SPINLOCK(Buffer Strategy Lock),然后从FREELIST上取下BUFFER,准备给新的PAGE使用,此时我们需要PIN住这个BUFFER,使之不能被BUFFER替换等操作使用。然后需要申请一个BUFFER CONTENT锁,来修改这个BUFFER,通过加buffer header lock来修改BUFFER头上的访问指针计数器等信息。然后就要开始读取PAGE的IO操作了,此时需要获得一个BUFFER IO锁,指示该BUFFER正在进行IO操作,从而避免在同一个BUFFER上的多个IO并发进行。IO结束后,这个BUFFER中已经包含了我们所需要的PAGE,此时我们需要把这个BUFFER加入到HASH CHAINS里,此时就需要一个buffer mapping锁,从而便于今后BUFFER扫描定位,这个锁有点类似Oracle的CBC闩锁,也是多个锁分区管理的,PG使用多个分区来提高并行效率。

下面我们来看一个例子:

此时我们在另外一个会话里查看一下BUFFER PIN的情况:

可以看到一个BUFFER是被PIN住了。此时我们如果执行VACCUM会发生什么呢?

可以看到VACUUM跳过了被PIN住的BUFFER,因为针对PIN住的BUFFER,PG无法对其中的PAGE做VACUUM这样的不兼容的操作。

此时如果做不兼容的vacuum freeze操作就会被锁住,要等待BUFFER PIN被移除。BUFFER PIN是一个共享锁,不会阻塞同一个PAGE上的并发写操作,不过这个共享锁还是会产生一些并发互斥的操作,比如会阻止VACUUM对这个PAGE进行回收整理操作,使VACUUM操作跳过这个PAGE,会阻止FREEZE操作,直到PIN住该BUFFER的所有锁全部移除。

因为PG数据库采用的是APPEND STORE模式,因此一个行的UPDATE会产生多个行副本,这对于PG的数据行的访问操作来说会增加额外的成本,在这里我们还需要考虑索引访问的成本问题。如果这些记录副本都存储在同一个PAGE里,那么处理起来成本相对还比较低,PG采用HOT来降低索引的维护和访问成本。如果多个TUPLE是分布在多个PAGE中,那么这个成本的增加就不可避免了。如果我们的应用系统中的某些表上的UPDATE十分频繁,那么这种额外的成本就会更大。再加上PG在访问数据时的各种锁的开销,这个叠加成本就更大了。

以VACUUM为例,如果我们的应用出现了BUG,打开一个CURSOR后忘记关闭了,或者一个死会话没有释放相关的CURSOR,那么某个或者某些BUFFER会被长时间PIN住,VACUUM每次都会跳过这些PAGE,时间长了,就会引发一些莫名其妙的问题。

希望今天看了这篇文章后,我们再去看PG等待事件中关于BUFFER的事件,可以更准确的了解到哪些等待事件代表什么含义,从而可以更好的定位问题。

正是因为PG的这种特性,在使用PG数据库的时候我们不能像使用Oracle那样肆无忌惮,如果做UPDATE操作,尽可能优化应用逻辑,让一条数据的UPDATE次数尽可能的减少。另外对于UPDATE十分频繁的表,或者需要对很多列进行UPDATE的宽表,其表的FILLFACTOR参数要适当减少,尽可能利用HOT来优化访问性能。另外,如果某张经常UPDATE的宽表是可以分拆的,那么尽可能把这张表分拆为多张表。

我和很多使用PG数据库的人交流过,有些人就说PG很好用,我们用了PG后系统一直都很稳定。有些朋友就说经常踩坑。实际上很多数据库都是有各种各样的坑的,如果你知道坑的存在,那就不容易踩坑了。有坑不可怕,不知道前面有坑才更可怕。


分享好友

分享这个小栈给你的朋友们,一起进步吧。

数据库专区
创建时间:2020-06-16 18:15:35
数据库是存放数据的仓库。它的存储空间很大,可以存放百万条、千万条、上亿条数据。但是数据库并不是随意地将数据进行存放,是有一定的规则的,否则查询的效率会很低。当今世界是一个充满着数据的互联网世界,充斥着大量的数据。即这个互联网世界就是数据世界。数据的来源有很多,比如出行记录、消费记录、浏览的网页、发送的消息等等。除了文本类型的数据,图像、音乐、声音都是数据。 [2]
展开
订阅须知

• 所有用户可根据关注领域订阅专区或所有专区

• 付费订阅:虚拟交易,一经交易不退款;若特殊情况,可3日内客服咨询

• 专区发布评论属默认订阅所评论专区(除付费小栈外)

技术专家

查看更多
  • 小雨滴
    专家
  • gaokeke123
    专家
戳我,来吐槽~