设为首页 收藏本站
查看: 2255|回复: 0

[经验分享] PostgreSQL vacuum 内核源码机理

[复制链接]

尚未签到

发表于 2016-12-21 10:34:34 | 显示全部楼层 |阅读模式
  为了能全面理解PG整个vacuum的过程,专门绘制了下面一个完整的过程图,用以记录其内核源码实现机理。整个过程比较复杂。大致分为以下几个部分:
  一、pg_ctl
  这个负责PG server起动,调用start_postmaster后,起动PG主server进程postmaster。后面任务交给postmaster来处理。
  二、postmaster
  负责起动autovacuum launcher,起动autovacuum launcher后台进程后,控制权交给launcher。
  三、autovacuum launcher和 autovacuum worker
  这两个进程的源码都在autovacuum.c中,autovacuum.c中的源码可以大致上为分两个阶段:
  第一个阶段:主要为launcher的职责。负责为将要起来工作的worker分配AutoVacuumShemStruct结构槽,并且选择一个最近最少vacuum或者最需要冻结xid的DB。
  然后将此dbid赋值给worker,并发送信号给postmaster,说已经准备好woker了,可以起动了。
  第二个阶段:主要为worker的职责。postmaster接收到launcher的信号后,起动AutoVacuumShemStruct中状态为startingwork的auto vacuum worker。
  主要是工作是fork一个进程,并将pid赋值给此worker,然后发信号给launcher,说你可以准备起下一个worker了。
  进入autovacuum worker后:
  1.首先收集需要vacuum或者analyze的表。需要vacumm的表的判断依据是Dead Tuples的值超过:vacuum_threshold + vacuum_scale_factor * num_tuples。
  需要analyze的表的判断依据是DML的记录超过此值:analyze_threshold + analyze_scale_factor*num_tuples。
  2.找到第一个需要vacuum的表,并将此表的 vacuum option参数赋值给autovacuum worker,即MyWorkInfo结构体(指向AutoVacuumShemStruct中的worker)。
  如cost_limit,cost_delay,cost_limit_base参数。其中cost_limit_base的值等于cost_limit的值。
  3.调整每个在running 的worker的cost_limit值。worker中有cost_limit和cost_limit_base两个变量。cost_limit和cost_limit_base的值,在刚开始没有经过balance时,是相等的。
  但是经过balance过,cost_limit的值会发生变化。而cost_limit_base的值基本上就是表级别用”alter table xxx set(autovacuum_vacuum_cost_limt=1000)”命令来设置的值。
  设置好后,在balance过程中,cost_limit_base的值基本上不变。因此才在名字上加了”base”用于区别。如果没有设置,cost_limit和cost_limit_base都是autovacuum_vacuum_cost_limit这个在postgresql.conf配置的值。
  表级别的设置值优先级高于postgresql.conf中定义的全局值。balance时,参考cost_limit_base的值对每个running worker 的cost_limit进行调整。cost_limit最大值
  不超过cost_limit_base,即需在[1,cost_limit_base]闭区间内。cost_limit值的意义其实就是每个毫秒时间内vacuum所能允许消耗的IO cost值。即:cost_limit/cost_delay。
  而这个cost_limit/cost_delay又会被autovacuum_max_workers个workers平分掉,而不是简单的做个限制。如果超过,就是最高以4倍的cost_delay来惩罚,这将导致vacuum过程严重变长。
  详细说明见”第6“步。
  4.balance完成后,接着就用上面的cost_limit和cost_delay值去更新VacuumCostDelay和VacuumCostLimit这两个值。并将VacuumCostBalance的值置为“0”。这三个值的意义在”第6“步中讲。
  5.接着去判断此次发起的是哪种类型的vacuum: vacuum full 还是lazy vacuum。如果是vacuum full,相当于重建relation,需要AccessExclusiveLock。如果是lazy vacuum,
  则是SharedUpdateExclusiveLock。lazy vacuum 还要判断是否需要full scan。如果是full scan,需要更新pg_class中的relfrozenxid值。partial scan只清理dead tuple和compact free space。
  请见另外一篇文章“PostgreSQL vacuum原理—vacuum揭秘”。
  6.最后就是去scan heap了。按每个block依次遍历。每遍历一个block都需要 delay一次。在这里上面“第4步”中的三个值就派上用场了。每次sleep的时间按公式:
  msec=VacuumCostDelay*VacuumCostBalance/VacuumCostLimit
  如果上面这个值大于4倍的VacuumCostDelay值,那么msec就等于“4*VacuumCostDelay”。否则就按上面公式算出的值进行sleep。sleep完成后,将MyWorkInfo中的cost_limit和cost_delay
  赋值给VacuumCostDelay,VacuumCostLimit,以适应balance过程。然后再次将VacuumCostBalance设置为“0”。
  其中VacuumCostDelay和VacuumCostLimit基本上每次balance后就不变了。唯有VacuumCostBalance值是在整个block遍历的过程中变化的,它的cost计算是根据当前page hit,page miss
  以及page dirty来计算的,请见另外一篇文章“PostgreSQL Cost Based Vacuum探秘”。因此如果一个表的update,delete操作很高,那么dead tuple就非常多,导致vacumm时,
  VacuumCostBalance值变高。因此如果要加快vacuum,减少一个表在vacuum时的delay时间,只有把cost_limit的值提高,也就是postgresql.conf中autovacuum_vacuum_cost中的值调大,
  才会使上面公式的值就小。
  上面还是太理论了,还是有点难懂的。我举个简单的例子来说明下cost的计算:
  假设当前有3个表需要vacuum,而且起了3个worker。每个表的autovacuum_vacuum_cost_limit都为默认值200,autovacuum_vacuum_cost_delay的值都为10ms。另外postgresql.conf中
  配置的这两个值也是默认值,分别为200和10ms。那么cost_limit 的值就是:200/3=66。当然,如果在每个表的cost_limit_base都不同的情况下,计算会复杂点。总体思路就是cost_limit_base
  大的表,分到的cost_limit值也大些。但是区间还是在”第3步”中的区间,即[1,cost_limit_base]。cost_limit的可配置范围在[1,10000];cost_delay的值在[1,100],单位是ms。
  计算公式我归纳如下:
  cost_total=sum(cost_limit_base/cost_limit_delay),每个runing worker都加起来。
  cost_avail=autovacuum_vacuum_cost_limit/autovacuum_vacuum_cost_delay,postgresql.conf中配置的值。
  每个worker的cost_limit=max(min(cost_avail*cost_limit_base/cost_total,cost_limit_base),1)。所以上面的值代入,得到约为66。
  PG用这种算法,完善实现了cost based vacuum。详细图见下:
DSC0000.jpg

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-317332-1-1.html 上篇帖子: postgresql在工作中 下篇帖子: PostgreSQL vacuum原理
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表