很多人会认为PostgreSQL中无回滚段是一个很大的缺陷,同时埋怨PG内核社区的人为什么还不赶紧把这个功能加上去。实际上PG内核开发人员没有把回滚段加上是有原因的,因为回滚段这个事情是有两面性的,目前PG这样没有回滚段时,虽然看起来好象需要vacuum做清理,好象会多产生一些IO,会产生很多负面的影响,实际上这种方式产生的IO与回滚段在理论上是差不多的,同时这种方式也有很多好处。使用回滚段后,虽然解决了一些问题,但也会带来一些棘手的问题。例如我们知道Oracle中使用了回滚段,如Oracle数据库宕机时如果有很多事务正在运行,这时数据库再启动后,需要把之前的事务做回滚,当没有回滚完成时,数据行上仍然有锁的,这时业务仍然不能正常操作,如果恰好碰到要回滚一些很大的事务,情况会更坏,而PG因为没有回滚段,异常宕机后,启动后可以很快进入正常工作的状态。
笔者认为主要是用户对PostgreSQL的一些vacuum的配置参数及相应的机制不太了解,导致了很多vaccum的问题出现。我们需要根据实际情况对vacuum这些参数进行一些调整。PostgreSQL中的一些vacuum参数是按照原先的机械硬盘配置的,这些参数都有一些保守,vacuum_cost_limit默认值为200,通常太小了,对于有cache的raid卡,这个值应该设置成1000左右,对于ssd,应该设置成10000。很多一些用户就是因为这个参数设置的太小,导致一些用户旧版本数据没有得到及时清理,导致数据库的年龄不断增加,当离20亿还有100万时,PostgreSQL为了安全,就会主动宕下来。autovacuum_vacuum_cost_delay的值也应该设置成10ms或更低,因为为了让系统更平稳,整理完2000个数据块后休眠20ms,不如设置成整理完1000个数据块后就休眠10ms,这样会让系统更平稳。所以正确的配置是把autovacuum_vacuum_cost_delay配置成10ms或5ms后,如果觉得vacuum影响大,应该把vacuum_cost_limit调小,而不是调整autovacuum_vacuum_cost_delay这个值。另外,对于事务繁忙的数据库autovacuum_max_workers默认值为3,也小了一些,这个参数表示可以同发做vacuum的数目,我们可以把这个参数设置成10,这样vacuum整理就更及时了。PostgreSQL参数autovacuum_freeze_max_age的默认值是2亿,如果我们不想让vacuum这么频繁的整理,这个参数值就有一些保守了,因为可用的是20亿,2亿就开始整理有些频繁了,这个参数可以改成5亿,有时设置成10亿也是可以的。因为每天上亿次的事务的数据库并不多,即使1天1亿个事务,10天才能用得完。这10天的时候也够vacuum把旧版本数据清理掉了。当然如果你的数据库vacuum也没有导致出什么问题,数据库也不繁忙,autovacuum_freeze_max_age的就保持默认值2亿,这在多数的数据库也不存在问题。另还有一些需要注意的事,vacuum并不能在一张表上做并发整理,所以表不能太大。有一些用户的一张表到达了好几十GB甚至上百GB, 这时vacuum整理这样的一张表有可能一天都没有整理完,这样就出问题了。所以对于大表来说需要做成分区表,一般表的记录超过3000万,就应该建成分区表。对于旧版本的PostgreSQL来说,PG是通过表的继承来实现的分区的,在10.X版本之前,建分区表的的语法不方便,导致了一些用户没有使用分区表。另外,即使是10.X之后,PG的分区表仍然是通过表继承实现的,性能会差一些,所以最佳实践是使用pg_pathman插件来实现分区表。很多人不知道pg_pathman,所以在分区表方面会遇到一些问题。
vacuum使用方法如下:
1、full vacuum与标准的vacuum还是有很大的区别的。vacuum只是将删除状态的空间释放掉,转换到能够重新使用的状态,但是对于系统来说该数据块的空闲空间并没有反应到系统的元数据中。类似oracle中高水位标记并没有下降。Full vacuum将会使空间释放的信息表现在系统级别,其实质是将当前删除记录后面的数据进行移动,使得整体的记录连贯起来,降低了“高水位标记”。
2、Vacuum analyze
analyze的功能是更新统计信息,使得优化器能够选择更好的方案执行sql。oracle中同样也有analyze,作用也相同,目前更多的使用的是dbms_stats包。统计信息收集和更新对于系统性能来说非常重要,与oracle维护类似,通常可以通过采用手动或者定制任务的方式。也有不同,oracle在进行imp后自动的对相应数据对象进行统计信息的收集和更新,而postgresql的恢复过程还没有集成到里面,需要手动去执行。
3、自动vacuum配置,自动vacuum的执行直接由autovacuum参数值决定,默认值是on。由于这些原因,在进行频繁的 VACUUM 操作时进行规定:标准 VACUUM进行回收时,生产环境不影响数据库库的正常使用(SELECT、INSERT、UPDATE、DELETE),并行使用,清理时不允许对表结构进行修改(ALTER TABLE)推荐使用该方案;VACUUM FULL,a、可以回收大量空间,但是比标准回收执行慢,b、运行时需要锁表。