暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

PostgreSQL Vacuum清理垃圾?

呆呆的私房菜 2024-07-31
274
    Whoami:5年+金融、政府、医疗领域工作经验的DBA
    Certificate:OCP、PCP
    Skill:Oracle、Mysql、PostgreSQL
    Platform:CSDN、墨天伦、公众号(呆呆的私房菜)



    阅读本文可以了解PostgreSQL VACUUM概念、日常运维及相关建议。




    01

    VACUUM概述
    • 通过上一篇文章 用pageinspect浅探下PostgreSQL的MVCC 我们可以了解到PostgreSQL为维护多版本并发控制功能,在数据库做update和delete操作的时候,会产生dead tuple。问题来了,如果任由这些dead tuple无限膨胀,浪费磁盘空间不说,还可能引发数据库性能问题,因此进行dead tuple的清理就显得格外重要了!没错,这个过程就叫做vacuum。


    • VACUUM 可以清理dead tuple、更新统计信息、重组数据和解决事务ID回卷问题。


    02

    VACUUM语法
    • vacuum:不要求获得排他锁,只需要找到旧版本数据,标记状态为不可用,不会进行空间合并;
    • vacuum full:需要lock table,这个操作除了进行vacuum,还会进行空间合并;
    • vacuum analyze:更新统计信息,使优化器能够选择更好的方案执行sql;
    • vacuum freeze:表记录冻结,可解决事务ID回卷问题。
      VACUUM [ FULL ] [ FREEZE ] [ VERBOSE ] ANALYZE [ table [ (column [, ...] ) ] ]


      03

      VACUUM形式
      • vacuum 标准形式:

      • 1. 回收dead tuple的磁盘空间,但是不会交给OS,而是为新tuple留着;

      • 2. 如果删除的记录位于表的末端,且没有tuple,其所占用的空间将会被物理释放并归还操作系统;

      • 3. 页内没有事务可见的tuple,即整个页都可以删除时,会做truncate操作,把尾部的这些页统一从文件中删除,文件大小和表所占空间也会减少;

      • 4. 标准形式vacuum可以和生产数据库DML操作并行运行,但在期间无法使用alter table等命令来更新表定义。

      • 5. vacuum会产生大量的I/O流量,这会导致其他活动会话性能变差。


      • vacuum  full形式:

      • 1. 通过把dead tuple空间之外的内容写成一个完整的新版本表来主动紧缩表,这会最小化表的大小,但是需要花费较长时间;

      • 2. 实质上将当前删除记录后边的数据进行移动,使整体的记录连贯起来,降低“high water marked”。 

      • 3. vacuum full重组了数据,会释放出来较大的磁盘空间,但存在如下弊端:

      • a. 会给表加上排他锁,阻塞相关表的操作;

      • b. 会创建一个表的副本,期间磁盘空间加倍,最大可能达到2倍。磁盘空间有限情况下,慎重执行vacuum full。


      • vacuum  analyze形式:可以调整指定字段的抽样率;

        # value取值0-1000,其中值越低采样比例越低,分析准确性也就越低,但analyze命令执行速度就更快
        alter table <table_name> alter column <columnname> set statistics <value>;


        # 查看当前系统缺省采样值
        show default_statistics_target;


        • vacuum  freeze形式:

        • 事务回卷指的是PostgreSQL的XID达到40亿后,XID会重置为0,而按MVCC机制规则,之前的事务可以看到新事务创建的元组,但新事务不能看到之前事务创建的元组,这违反了事务的可见性。

        • 1. PostgreSQL默认的存储引擎事务可见性依赖行头的事务号,因为事务号是32位的,会循环使用;

        • 2. 事务ID由32位数保存,而事务ID递增,当事务ID用完之后,会出现事务ID回卷问题,可以通过vacuum freeze来解决问题;

        • 3. 在一条记录产生之后,如果再次经历了20亿个事务,必须对其进行freeze,否则数据库会认为这条记录是未来事务产生的(可见性判断)可以调整指定字段的抽样率;

          # PostgreSQL事务ID的特殊意义:
          # 0 代表 invalid事务号
          # 1 代表 bootstrap(辅助程序)事务号
          # 2 代表 frozon事务号


          # 注意:
          # 1. frozon事务号比任何事务号都要老,可用的有效最小事务号为3;
          # 2. vacuum时将所有已提交的事务ID均设置为2,之后所有的事务都比frozon事务新
          # 3. 因此vacuum之前的所有已提交的数据对之后的事务可见,PostgreSQL通过这种方式实现了事务ID的循环利用


          04

          autovacuum
          • autovacuum 是PostgreSQL里非常重要的一个服务器进程,在一定条件下会触发执行。

          • autovacuum 参数控制autovacuum进程是否打开,默认为on,作用如下:

          • 1. 清理dead tuple,并对表进行分析;

          • 2. 更新可用空间映射(free space map),以便跟踪表块中的可用空间;

          • 3. 更新仅索引扫描的可见新图(visibility map);

          • 4. freeze表行,以便事务ID计数器可以安全的环绕。

            autovacuum触发条件:
            # 1.autovacuum_naptime:autovacuum唤醒间隔时间
            # 2.表上(updte、delete >= autovacuum_vacuum_scale_factor * reltuples(表记录数) + autovacuum_vacuum_threshold
            # 3.触发vacuum analyze:表上(insert、update、delete) >= autovacuum_analyze_scale_factor * reltuples (表记录数) + autovacuum_analyze_threshold
            # 4.触发vacuum freeze:指定表上事务的最大年龄配置参数 autovacuum_freeze_max_age,默认为2亿



            05

            vacuum使用建议
            • 1. 开启全局auvacuum,设置参数autovacuum=on;

            • 2. 持续关注表中dead tuple的状况、表级计划性的执行vacuum;

              # 查询需要vacuum的表,即表的dead tuple的量或者比例,默认情况下可能有少于20%的dead tuple
              # 可通过以下sql命令查询表的空间使用情况:
              select relname, n_live_tup, n_dead_tup 
              from pg_stat_all_tables 
              where n_dead_tup desc;
              • 3. 可使用安装目录bin下的vacuumdb或vacuumlo工具对数据进行手动清理;

              • 4. 适当调大参数maintenance_work_mem,可加快vacuum的执行速度;

              • 5. PostgreSQL 9.5引入了一个新的参数:jobs参数,可以并行运行vacuum;

              • 6. 对于有大量update的表,vacuum full是没有必要的,因为它的空间还是会则呢盖章;

              • 7. 定期监控数据量变化较大的表,确认其磁盘页面占有量接近临界值,可考虑vacuum full。

                # 注意:
                1. vacuum只会删除那些已经结束的事务所关联到的旧的已经不用的数据;
                2. 如果一个事务还在执行,autovacuum就不会处理这个事务;
                3. 如果应用中大量使用了table lock,会导致autovacuum无法执行。



                本文内容就到这啦,阅读完本篇,相信你对PostgreSQL的VACUUM垃圾清理机制有了一定的了解了吧!我们下篇再见!

                点击上方公众号,关注我吧!

                文章转载自呆呆的私房菜,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

                评论