开发者学堂课程【PolarDB for PostgreSQL 开源人才初级认证培训课程:vacuum 处理】学习笔记,与课程紧密连接,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/1077/detail/15554
vacuum 处理
内容介绍:
一、并发 vacuum 概述
二、可见性地图概述
三、冻结概述
四、Autovacuum 介绍
五、Full VACUUM
这节课讲 Polar DB vacuum的操作,vacuum 是 Polar DB 里头所特有的一种维护工作,为什么要有这个进程,它怎么操作。
一、并发 vacuum 概述
1.vacuum 工作内容
Vacuum如果中文翻译过来叫做真空。可以根据他的工作内容,可以把它理解为是一个空间清理,空间整理这么一个工作,他最主要的工作内容就是把数据块当中被删除的行的空间,把它释放出来,首先要了解polarDB,它对数据库当中被删除的行是怎么处理的,假如当前这个数据块,已经有两行数据,一个用户做了一个update操作,比如说他修改了这一行,那么polarDB它的操作方式不是在当前这一行进行修改,他会把原来的这一行标识为删除,然后会在这个数据块insert一行新行,这个被标识为删除的行,他的空间不会立刻去释放,在什么时候释放,谁去释放,就是由vacuum来操作。所以vacuum的操作就是做空间整理,他除了这个工作以外,他还做把老的PXID修改的给冻结,为什么要冻结,冻结只有polarDB或者PG所具备的一个特征。除了这个之外,他还做表统计信息的收集,这个非常重要,这个收集的信息是为了给优化器提供可用的答案进行做参考,除了这个以外,还会更新一些表的文件。
2.vacuum 处理流程
首先vacuum的操作过程,实际上的过程可以分为三部分,首先是怎么处理前的部分,处理前的部分他要到各个数据库里头去搜一下,哪一些表达到了需要整理的一个条件,vacuum的操作条件,他在他polarDB里是有规定的,它有一个专门的一些参数来制定。如果你这个表达到了这个条件,它就会从各个数据库里头把需要整理的这个表组成一个例子,准备完之后,接下来就到了清理阶段,清理阶段就是把包含着被删除的行,测完后同时更新一下这两个文件,做完以后就是善后工作,善后是如果说这个表有三个块,空间整理完以后,发现最后没有数据,就没有办法那么减少这个表的尺寸,那么polarDB会把这个数据块,从这个表中给删掉,这样子就让表包含有两个块,可以减少数据文件的尺寸。弄完以后,他会做统计信息。如果需要会把不必要的log、clog打给上面,所以看一下vacuum的进程,它平时所做的操作的内容比较多,同时也比较重要。
3.vacuum 操作前后对比
这个vacuum操作的一个前后对比,举个例子,比如这个表,当前三个数据块,三个数据块其中第0个数据块,当前的情况是有一行和这一行是被删除的行,在polarDB它被标注的tuple的就是死行,死元组,那么polarDB它的称呼不像olger,olger函数就叫做log,但是它叫tuple翻译过来叫做元组。那么假如这个块当中的一个被删掉,那做完back后来看polarDB,它就会把被删除的行的空间释放,然后再把原来这两个数据做一个整理,这样子数据就存放的就更加紧凑,然后将来在存放新数据的时候就放得更多。同时注意被删除的这个函的这个指针,他没有删掉,因为将来这个指针,比如说我现在又插入一个新行,他就根据指针把这个指针给新行,维护的操作就少一点,可以提高效率。
二、可见地图概述
1.可见性地图作用
在做vacuum的时候,正常情况,它是要把表的所有的数据块给找一点,然后进行清除,那么我为了提高他的效率,比例,就用了VM数据文件,叫做可见性地图,可见地图是为了提高这个vacuum的效率,举个例子,比如当前有三种数据块,这个数据块里假如第二个块,这个块他那里没有包含被删除的行,那么他就在vacuum地图上面用1来表示,那么将来他在做vacuum的时候,如果他去扫描这个页的这一块的时候,他一看这个页的状态是1,将来在处理的时候,这块它就跳过去,因为里面没有包含我需要进行空间整理的数据我就跳过去,那这样子就会提高vacuum的效率,所以这是可见性地图的一个作用。
2.增强的可见地图
那么可见地图除了提高效率,同时它还包含了将来去做冻结的时候它的一个效率。
VM在9.6版中得到了增强,以提高冻结处理的效率。
新的VM显示页面可见性和关于在每个页面中元组是否冻结的信息。
3.事务 IDS 结构(polarDB 中的 IDS)
接下来polarDB为什么要去冻结PXID,
这就是数据库为了去描述这个事物操作的一个先后顺序,要给事务分配一个ID号,那么aorocal生成的ID号,叫做SCN号,这个应该都明白,叫事务处理号,事务改变号。那么polarDB他不叫SCN号,它叫做txid号。就是事务ID号,那么aorocal的这个SCN号,它是以整数的形式来增长,而且他还告诉我ID号可以用100年,所以这个ID号我们可想而知,可能将来他的数量是比较大的,但是polarDB他用的这种方式,不是这种无限大的整数,他用到了一个循环的使用,就是他最大的可用的这个事务ID,总共有42亿,这个42亿是一半一半的用的,比如前面用前面20亿的时候,代表当前正在用的这些事务ID所修改的行,把它当作是过去的修改的这些行,我们把它描述为是可见,那么后21亿,这个是未来的,未来就是未来不可见,根据他的规则,这些事务ID所修改的行是不可见的,
举个例子,原来有个数据块,这个数据块这一行的数据,它修改他的事务ID,比如说很大是由这个事务ID去改的,那么这个事务ID假如说是属于这个部分,就是后21亿的,那么根据他的规则,那么这个块的这一行,将来去扫描的时候,对于我们用户来说是不可见的。就是它有这么一个规则,哪怕这个TXID有总共虽然只有42亿,但是可以不断的循环,如果前面先用,前面的这个21亿用完以后再用后面的21亿,然后用完之后又回来用前面的21亿,是这样子循环使用的。
三、冻结处理概述
1.冻结处理
冻结是基于他的一个可见性规则,如果这个ID,比如是一个数据块,然后有一行数据,在这个数据库里有一行的数据标记了,它是由第100个事务ID修改好了,然后下面这个数据库用了很久,现在,我的数据库以我的事务ID,已经用到了后21亿,比如说是21亿加100。已经用到了这里,那么根据他的规则,你前20亿用到的这个事物ID就不可用了,这个前面的21亿以前的这个事物,所修改的行,按照正常情况下就不可见,但是这个数据块里头有数据,又不得不让你看见,那怎么办?那就要在这个行的某一个位上面做个标记,这个标记就是冻结的标记,为什么叫做冻结,其实,它其实就是做了一个英文标记,就是做了一个英文标记,那么这个英文它翻译过来叫做冻结,所以就把它称为冻结,就是在这一行做一个标记,标记说将来这一行是可见的,如果没有这个标记,那么这一行就找不到。所以这个冻结就是把很早以前超过了21亿的事务ID,以前这个事务ID所修改的行,做一个标记,那么这样的标记完以后,很早以前的事务ID修改的行,才能够把他给访问看得到。
在做标记的时候,要根据它的规则,是前面先用了21亿,用完以后,把前面用的21亿里头,比如把这一部分你所操作的这些事物,都帮你冻结一下,那么一种情况就是用完以后统一冻结,那这个冻结的时候,操作是非常巨大的,肯定不行,所以那polarDB它是平时运了一点一部分事物ID以后,它可能就冻结一下,然后又运了一部分以后又冻结一下,等于说将来如果要到了换另外21亿事务ID使用的时候,等于要冻结的时候,前面几乎都已经冻结完了,只要冻结一小部分没有冻结完的ID就可以了,换句话来说,把一个庞大的一个需要做的工程,把他分到平时,切成若干部分,先逐步的完成,到了最后,只要完成一小部分的就可以达到这个目标,把这个项目完成,就这么简单。
所以在冻结的时候,就分为小冻结和大冻结,在polarDB里把它叫做惰性冻结和急性冻结,之所以这么说,是按照他的意思翻译过来,在理解的时候,可以把惰性冻结理解为小冻结。然后把急切冻结理解为大冻结,冻结的多一点。还可以理解为,小冻结可以把它看作住的房间,要保持干净,小冻结可以理解为做日常的卫生,大冻结可以理解为年终大扫除。就可以把很大的一个工程,平时一步一步的做直到把这个大部分做好。
2.惰性冻结模式
下面介绍一下惰性冻结他是怎么冻结?它是根据一个公司,就是发生冻结的时候,哪一些事物ID要被冻结掉,当然它这里的控制,就是要被冻结的ID等于这个叫做oldestxmin就是当前事务中最小的一个,假设是100-102,都要去减去free_vacuum_min_age一般为五千万是个常数,都要去减掉五千万。
3.惰性冻结示例
我现在最小的事务ID是50,002,500,这是当前正在用的最小的事务ID,在这个时候做惰性冻结,那么按照公式,是把当前最小的减去五千万,等于2500,意味着要把小于或者等于2500的事务ID都冻结掉,首先计算出你要冻结的ID是多少,然后找出对应的ID,看VM比,VM比是如果有三个数据块,加入没有被标记,如果VM中的1代表Tuple1、2、3,里面没有被标记的行,就会跳过这个数据块,惰性冻结只冻结数据块中有被scan的,凡是事务ID小于2500的都在后面有标记叫做FROZEN,用这个标记来表示把它要冻结,比如这个块,这个块有三个行,有一行是被事务ID3000修改的,而我算出小于等于2500会被标记,那么这个块中前面两行会被标记,第三行不会被标记。所以平常的时候就会对一些事务ID进行标记,标记的时候要减去五千万,要小于这个数才能被标记。可以理解为这个数据块中包含了太早以前就修改的行。
4.急性冻结触发条件
急性冻结类似大扫除,数据字典中pg_database datfrozenxid是曾经标记过的,假如你标记过的事务ID,小于正在使用的事务ID的最小值减去一亿五千万,也就是说你的事务ID至少用过一亿五千万次之后才会被冻结,又用了一亿五千万做一次急性冻结,急性冻结它的范围就会大一点。看实例,如果还没有发生一亿五千万次,统一的会被560标示,只有在发生一亿五千万次之后才会被急性冻结。
5.急性冻结示例
如果已经发生一亿五千万次,polarDB是如何做的,假如已经用到的
最小的事务ID是一亿五千万零两千,我要发生的冻结事务ID是当前的减去一亿五千万,小于这个数的被急性冻结,那么当前数据块中,polarDB会扫描这些行,把事务ID小于算出来这个数的全都在后面标记上冻结标示,之后在运作代码时,这些行都能被识别出来,大于这个数的,可以理解为刚刚被使用,那么这一行就不会被标识,只有很久以前被修改过的行,这些行的事务ID才会被冻结,最近很新修改的行不会被冻结,之后很久才会被冻结。惰性冻结在平时就已经开始了,而急性冻结只有在够了一亿五千万才开始,惰性冻结只要做vacuum操作,polarDB都会去判断这个数据块中要不要冻结。
6.冻结后如何标记
如果在ID冻结之后,比如是急性冻结,这些事务ID号是这些,做完以后所有的列上面就会写上被冻结时候它的ID是多少,因为够一亿五千万次之后就会进行急性冻结,而事务ID用过21亿才会翻一翻。
7.显示表的冻结ID
在我的表当中,假如我的表发生过惰性冻结。这个过程也可以看得到,通过这个数据字典可以看到,比如这个表,曾经被惰性冻结的ID,那么如果看到这个651,其实是意味着你这个表,可能是由这个事务ID创建的,这个事务所创建的ID,当做第一次被冻结。那实际上,0在表上面就意味着如果这个表是数据字典,就是这个数据初始化的时候创建的。
8.提高惰性冻结效率
因为急性冻结,他要把曾经发生过的事物所修改的行要做个标记,所以这个操作实际上它是很大的,或者可以理解为它的操作是比较大的,那么如果说你在冻结的时候,操作太大。所以它的polarDB为了提高效率。一个项目看他的VM。假如里面有一表示的意思就是上一次冻结以后,不管是急性冻结还是惰性冻结。只要你下一次冻结以后,如果没有发生任何的变化,状态为1。换句话来说,如果这个号从来没有改变过,下一次发生急性冻结的时候这个块就直接跳过,因为前面冻结过,而且也没有发生变化,那么凡是0冻结过的代表这两种,一个是擅自冻结过以后,一个是擅自惰性冻结没有发生,因为有可能比这个再多一次,在做惰性冻结的时候,可能没有做过,来到我这做一次急性冻结。
比如上次在做惰性冻结的时候,因为这个数据库里没有包含被删除的,所以跳过去,但是,这一次也跳过去这一次及其冻结的时候还要跳过去,还有就是冻结过以后,这个数据库里又被修改,里面又包含有很多可能,这个被修改的也会被标注,凡是状态他都要去做。防止它跳过去,这样可以让他来减少动机的一个工作,这就是怎么样用VM来提高冻结的效率,所以我们前面讲的这个,每一张表都一样,每一张表他的数据文件都有三类,比如第一类是纯放数据的,文字是FSM,还有一个文件是VM里头存放,就是可见性。
四、Autovacuum 介绍
刚才说了半天这个问题谁去做,怎么做,什么时候做,从polarDB9.6后,他就有了一个专门的一个后台进程叫做Autovacuum,它是怎么定义呢?是每十分钟做一次,由这个参数来定义,定义每期每次做的时候呢,默认是三个进程去做,每个进程同一时间只能负责一个数据库里头的表,当然,如果我们想增加他这个Autovacuum的一个进程数,可以用autovacuum_max_workers参数来添加。
五、Full VACUUM
那下面讲一下Full VACUUM,vacuum他分普通vacuum和Full VACUUM,如果只是做了普通的vacuum,比如当前的有三个块,然后灰色的这个,标志为都是被删除的,那做了一个vacuum以后,假如说现在做的是普通的vacuum,那么vacuum之后,这三个块还保留,最后只剩下一两行的数字,比这个数据块还高,也就是说普通的操作完以后,文件的大小不会发生变化。这三个块现在还是三个,但是我们看到情况会发现,其实每个块里面,数据其实很少,我没必要的话,可能这里头只要一个块可能就可以,所以假如在空间整理的时候,如果你想减少数据文件的尺寸,那就可以做一个full vacuum了。
当把这个就是被清理的这个弄完以后,他首先也是先把这个块当中被删除的行的空间,把它给清理掉,最后剩一行,然后接下来他会怎么做呢?会再新建一个数据文件然后给他分一个块,接下来把原来剩下的这些把它放到这个块里。放完以后,然后把原来的这个数据文件的删掉。所以一删掉以后,原来的这个数据文件的名字就变了,就得变成新的。这是full vacuum的一个例子操作。
那下面讲一讲,比如什么时候要做full vacuum,要做full vacuum,就是如果检测到这个数据块当中数据块很多,但是里面每个块当中可用的空间很多,那这时候可以做full vacuum。可以这么做一下,首先创建一个插件,这个插件是不支持的,polarDB社区版的可能不支持,企业版的支持,不支持也没关系,我们主要说明一下怎么做,将来我把一个表大部分的数据删掉了,删完以后来看一下,其实,可以复印这个差距,可以看这个表的统计,
这个社区版的它不支持这种,这个差距,主是讲一下应该怎么去诊断,那么一开始,假如有这个插件,你可以去看一下,比如你当前我这个表当中总共有多少个数据块。然后看每个数据库里可用的空间有多少,只有99个字节,意味着我这块当中差不多都用完了,都有数据,那么接下来,做一个delete操作以后,我可能把表当中很多行的做法删掉,然后这时候,我们做了一个普通的vacuum,以后会发现这个总共的数据块没有发生变化,但是我们可以看到这个块当中平均已经空出差不多7K的数据,空间都是空的,也就是你可用的空间已经达到了80%,那就意味着这个块当中,经过空间处理完以后,很多被删除的行的空间已经释放,目前,只剩下一小部分。
如果是这样,就可以做full vacuum,看一下做完full vacuum以后,最大的一个变化是你的使用的块变少了,不需要那么多,所以full vacuum就是刚才看到的,会把剩下的数据做整理,整理完以后放到一个新的数据文件上面,然后把老的数据给删掉,这样就可以减少数据文件的尺寸
那下面就可以演示一下,比如在删除之前,看了一下这张表的统计,当时总共占了94个数据块,下面删掉一部分的数据,删完以后,如果是做一个普通的 vacuum,再查查看会发现这个统计信息的时候还是94个块,它没有变,但是如果做了 full vacuum,那我们再看一下这个数据块的统计,会发现只要用十个块就够了,明白这样子的好处就是将来这个表如果做全表扫描的时候,而做了full vacuum以后,你只要扫描十个,所以可以提高全表扫描的效率。那么这一点,跟Oracle也比较像是,Oracle 表预了一段时间以后,如果里头被删除的行比较多,是不是也要做一个空间,整理完以后,你全表扫描,所访问的数据块,就会减少,这样子就会提高我们访问的效果。
学习了 vacuum 操作,它是一个非常重要的进程,主要做的工作就是清理被删除的行,做冻结,特别是冻结,如果第一次学 polarDB,要理解为什么要冻结,它怎么冻结,冻结的过程。