3年部署3000套PG实例的架构设计与踩坑经验( 六 )


PostgreSQL的MVCC实现机制带来的问题是如果垃圾回收不及时容易导致数据文件膨胀 , 这也是很多人吐槽PostgreSQL的地方 。 不过 , 不能单纯地把PostgreSQL的MVCC机制视作一个槽点 , 只是MVCC的不同实现方式而已 。 不知道大家注意到没有 , 很多新兴的分布式数据库库 , 也都采用了类似PostgreSQL标记删除的MVCC机制 。
作为PostgreSQL的使用者 , 我们需要做的事是要确保PostgreSQL的垃圾回收工作能够正常运作 。 具体有下面几件事情要做 。
1)autovacuum参数调优
PostgreSQL中有一个后台的autovacuum进程专门负责回收垃圾 , 我们可以根据数据库的配置和业务特点对autovacuum进行合理的参数设置 , 确保autovacuum回收垃圾的速度足够快 , 对数据库负载冲击又比较平滑 。
比如下面几个参数:

3年部署3000套PG实例的架构设计与踩坑经验
本文插图
其中 , 最需要修改的是autovacuum_vacuum_cost_limit , 其含义是一次回收最多消耗多少cost则暂停一会(autovacuum_vacuum_cost_delay的设定值) 。 默认值为200 , 这个值对于现代的设备显得太小 , 容易导致垃圾回收速度跟不上垃圾产生的速度 , 使用SSD时可以考虑把它设置为10000 。
另外 , autovacuum默认在表中被更新的元组比率达到20%的时候启动垃圾回收 , 对于亿级别的大表 , 会导致一个问题 。 就是一次垃圾回收的任务太大 , 垃圾回收时间过长 。
所以建议采用以下优化措施:

  • 对过大的表进行分区控制单表的大小:比如单表控制在1亿记录或10GB以下;
  • 对大表单独调优autovacuum_vacuum_scale_factor参数:autovacuum_vacuum_scale_factor参数默认值是0.2 , 大表可适当调小 , 比如设为0.05 。
关于autovacuum , 详细可以参考一下这篇文章:
http://www.postgres.cn/v2/news/viewone/1/387
2)自动释放过长事务
PostgreSQL在垃圾回收时会保留对当前的存活事务可见的死元组 。 如果数据库中有一个执行时间特别长的事务 , 那么在这个事务存活期间数据库中产生的所有垃圾元组都无法被回收 。 这种长事务有时侯不是来自我们正常的业务访问 , 而是来自一些异常场景 。 我们可以在数据库中设置一些超时参数 , 使得在异常情况下 , PostgreSQL可以及时把事务终止 。
可以参考下面几类超时参数设置:
  • 释放长时间空闲的事务
idle_in_transaction_session_timeout = 3600s
  • 释放长时间拿不到锁的事务
lock_timeout = 60s
  • 释放已无法继续通讯的空闲连接
tcp_keepalives_idle = 60
tcp_keepalives_count = 10
tcp_keepalives_interval = 5
  • 限制SQL的最长执行时间:如果业务上有一个允许SQL最长执行时间的要求 , 可以把这个值作为SQL超时 , 通过statement_timeout参数或者通过客户端驱动的API进行设置 。 确保SQL执行时间过长时能被时取消 。
3)监控垃圾回收相关的数据库状态
除了前面介绍的措施 , 我们还需要对垃圾回收相关的一些数据库指标进行监控 , 一旦发生异常可以及时发现和处理 。 以下是我们在生成环境部署的一些和垃圾回收相关的监控项 , 大家可以参考一下 。
3年部署3000套PG实例的架构设计与踩坑经验
本文插图
>>>>
参考资料