精华内容
下载资源
问答
  • 小米真空卡 Home Assistant的Lovelace UI中的各种机器人吸尘器的简单卡 集成支持以下品牌/型号的大多数吸尘器:小米,Roomba,Neato,... - url : /hacsfiles/lovelace-xiaomi-vacuum-card/xiaomi-vacuum-card.js
  • 真空卡 Lovelace UI的吸尘器卡 ...使用UI:配置→ Lovelace仪表板→资源选项卡→单击加号按钮→将Url设置为/local/vacuum-card.js将资源类型设置为JavaScript Module 。注意:如果看不到“资源”选项卡,则需要
  • Pfeiffer vacuum book
  • Lovelace小米真空地图卡 就像在Mi Home应用程序中一样,此卡可让您使用实时或静态地图指定目标或开始分区清理。 另外,您可以定义区域列表并选择要清洁的区域。 前往目标 分区清理 定义区域 配置选项 ...
  • vacuum-源码

    2021-03-22 14:55:33
    vacuum
  • bitstamp-vacuum-源码

    2021-05-16 22:37:41
    编辑connection.js以获取数据库凭证 在执行该进程之前,请检查该进程是否尚未运行(htop) nohup node main.js > ../bitstamp-vacuum.out 2> ../bitstamp-vacuum.errors.out &
  • 这是Xiaomi Mi Robot Vacuum插件。 由于Apple Homekit尚不支持吸尘器设备,因此该插件会将机器人作为风扇添加到您的Home应用中。 特征 打开/关闭。 禁用时,它将自动返回到充电座。 通过调节风扇速度来控制吸力。 ...
  • Femtosecond (fs) pulse laser ablation of silicon targets in air and in vacuum is investigated using a time-resolved shadowgraphic method. The observed dynamic process of the fs laser ablation of ...
  • 我觉得下面这段文字应该能够描述清楚 PostgreSQL 的 vacuum. 日常数据库维护工作 作者:小P 来自: LinuxSir.Org 摘要:为了保持所安装的 PostgreSQL 服务器平稳运行, 我们必须做一些日常性的维护工作。我们在这里...

    我觉得下面这段文字应该能够描述清楚 PostgreSQL 的 vacuum.

    日常数据库维护工作 作者:小P
    来自: LinuxSir.Org
    摘要:为了保持所安装的 PostgreSQL 服务器平稳运行, 我们必须做一些日常性的维护工作。我们在这里讨论的这些工作都是经常重复的事情, 可以很容易地使用标准的 Unix 工具,比如cron 脚本来实现;
    +++++++++++++++++++++++++++++++++++++++++++
    正文
    +++++++++++++++++++++++++++++++++++++++++++

    1. 综述;
      为了保持所安装的 PostgreSQL 服务器平稳运行, 我们必须做一些日常性的维护工作。我们在这里讨论的这些工作都是经常重复的事情, 可以很容易地使用标准的 Unix 工具,比如cron 脚本来实现。 不过,设置合适的脚本以及检查它们是否成功执行则是数据库管理员的责任, 一件很明显的维护工作就是经常性地创建数据的备份拷贝。 如果没有最近的备份,那么您就没有从灾难中恢复的机会(比如磁盘坏了,失火,误删了表等等)。
      其它主要的维护范畴的工作包括周期性的 “vacuuming” (清理)数据库。
      其它需要周期性注意的东西是日志文件的管理。
      PostgreSQL 和其它数据库产品比较起来是低维护量的。 但是,适当在这些任务上放一些注意将更加能够确保我们的愉快工作和获取对这个系统富有成效的经验。 操作环境:PostgreSQL8.2+Ubuntu 7.04
    2. 日常清理;

    2.1 VACUUM;

    2.1.1 语法结构;

    VACUUM [ FULL | FREEZE ] [ VERBOSE ] [ table ] 
    VACUUM [ FULL | FREEZE ] [ VERBOSE ] ANALYZE [ table [ (column [, ...] ) ] ] 
    
    

    2.1.2 描述;

    VACUUM 回收已删除元组占据的存储空间。 在一般的 PostgreSQL 操作里, 那些已经 DELETE 的元组或者被 UPDATE 过后过时的元组是没有从它们所属的表中物理删除的; 在完成 VACUUM 之前它们仍然存在。 因此我们有必须周期地运行 VACUUM, 特别是在常更新的表上,如果没有参数,VACUUM 处理当前数据库里每个表, 如果有参数,VACUUM 只处理那个表,简单的 VACUUM (没有FULL) 只是简单地回收空间并且令其可以再次使用;
    2.1.3 参数;

    FULL    --------- 选择"完全"清理,这样可以恢复更多的空间, 但是花的时间更多并且在表上施加了排它锁。 
    FREEZE  --------- 选择激进的元组"冻结"。 
    VERBOSE --------- 为每个表打印一份详细的清理工作报告。 
    ANALYZE --------- 更新用于优化器的统计信息,以决定执行查询的最有效方法。 
    table   --------- 要清理的表的名称(可以有模式修饰)。缺省时是当前数据库中的所有表。 
    column  --------- 要分析的具体的列/字段名称。缺省是所有列/字段。 
    
    

    2.1.4 为什么要用VACUUM;

    VACUUM命令的含义为:垃圾收集以及可选地分析一个数据库。VACUUM回收已删除元组占据的存储空间。在一般的 PostgreSQL 操作里, 那些已经 DELETE 的元组或者被 UPDATE 过后过时的元组是没有从它们所属的表中物理删除的; 在完成 VACUUM 之前它们仍然存在。 由于以下几个原因,我们必须周期性运行 PostgreSQL 的 VACUUM 命令∶ 1.恢复那些由已更新的或已删除的行占据的磁盘空间。
    2.更新 PostgreSQL 查询规划器使用的数据统计信息。
    3.避免因为事务 ID 重叠造成的老旧数据的丢失。 对上面每个条件进行 VACUUM 操作的频率和范围因不同的节点而不同。 因此,数据库管理员必须理解这些问题并且开发出合适的维护策略。
    建议在经常VACUUM(清理)(至少每晚一次)生产数据库, 以保证不断地删除失效的行。尤其是在增删了大量记录之后, 对受影响的表执行 VACUUM ANALYZE 命令是一个很好的习惯。例如:

    sir=# VACUUM VERBOSE ANALYZE access ; 
    信息:  正在清理 (vacuum)  "public.access" 
    信息:  index "access_pkey" now contains 0 row versions in 1 pages 
    DETAIL:  0 index row versions were removed. 
    0 index pages have been deleted, 0 are currently reusable. 
    CPU 0.00s/0.00u sec elapsed 0.00 sec. 
    信息:  "access": found 0 removable, 0 nonremovable row versions in 0 pages 
    DETAIL:  0 dead row versions cannot be removed yet. 
    There were 0 unused item pointers. 
    0 pages contain useful free space. 
    0 pages are entirely empty. 
    CPU 0.00s/0.00u sec elapsed 0.00 sec. 
    信息:  正在清理 (vacuum)  "pg_toast.pg_toast_16464" 
    信息:  index "pg_toast_16464_index" now contains 0 row versions in 1 pages 
    DETAIL:  0 index row versions were removed. 
    0 index pages have been deleted, 0 are currently reusable. 
    CPU 0.00s/0.00u sec elapsed 0.00 sec. 
    信息:  "pg_toast_16464": found 0 removable, 0 nonremovable row versions in 0 pages 
    DETAIL:  0 dead row versions cannot be removed yet. 
    There were 0 unused item pointers. 
    0 pages contain useful free space. 
    0 pages are entirely empty. 
    CPU 0.00s/0.00u sec elapsed 0.00 sec. 
    信息:  正在分析 "public.access" 
    信息:  "access": scanned 0 of 0 pages, containing 0 live rows and 0 dead rows; 0 rows in sample, 0 estimated total rows
    VACUUM
    
    

    这样做将更新系统目录为最近的更改,并且允许 PostgreSQL 查询优化器在规划用户查询时有更好的选择。
    不建议日常使用 FULL 选项,但是可以在特殊情况下使用。 一个例子就是在您删除了一个表的大部分行之后,希望从物理上缩小该表以减少磁盘空间占用。VACUUM FULL 通常要比单纯的 VACUUM 收缩更多表的尺寸;
    2.2 恢复磁盘空间;

    2.2.1 概述;
    在正常的 PostgreSQL 操作里, 对一行的UPDATE或DELETE并未立即删除旧版本的数据行。 这个方法对于获取多版本并行控制的好处是必要的: 如果一个行的版本仍有可能被其它事务看到,那么您就不能删除它。 但到了最后,不会有任何事务对过期的或者已经删除的元组感兴趣。 而它占据的空间必须为那些新的元组使用而回收, 以避免对磁盘空间增长的无休止的需求。这件事是通过运行 VACUUM 实现的。
    很明显,那些经常更新或者删除元组的表需要比那些较少更新的表清理的更频繁一些。 所以,设置一个周期性的 cron 任务 VACUUM 那些选定的表,而忽略那些已经知道变化比较少的表. 这个方法只是在您拥有大量更新频繁的表和大量很少更新的表的时候有意义 — 清理一个小表的额外开销根本不值得担心; VACUUM 命令有两个变种:

    第一种形式,叫做"懒汉 vacuum"或者只是 VACUUM, 在表和索引中标记过期的数据为将来使用;它并不试图立即恢复这些过期数据使用的空间。 因此,表文件不会缩小,并且任何文件中没有使用的空间都不会返回给操作系统。 这个变种的 VACUUM 可以和通常的数据库操作并发执行;

    第二种形式是 VACUUM FULL 命令。 这个形式使用一种更加激进的算法来恢复过期的的行版本占据的空间。 任何 VACUUM FULL 释放的空间都立即返回给操作系统。 但是,这个形式的 VACUUM 命令在进行

    2.2.2 VACUUM FULL;
    VACUUM FULL 一个表的时候在其上要求一个排他锁。 因此,经常使用 VACUUM FULL 会对并发数据库查询有着非常糟糕的影响;
    标准形式的 VACUUM 最适合用于维护相当程度的磁盘用量的稳定状态。 如果您需要把磁盘空间归还给操作系统,那么您可以使用 VACUUM FULL — 不过如果释放的磁盘空间又会很快再次被分配又怎样? 如果维护更新频繁的表,那么中等频率的多次标准 VACUUM 运行方法比很低频率的 VACUUM FULL 更好;

    对于大多数节点而言,我们推荐的习惯是在一天中的低使用的时段安排一次整个数据库的 VACUUM, 必要时外加对更新频繁的表的更经常的清理。 (有些环境下,对那些更新非常频繁的表可能会每几分钟就 VACUUM 一次。) 如果您的集群中有多个数据库,别忘记对每个库进行清理;
    vacuumdb 脚本可能会帮您的忙;
    如果您知道自己刚删除掉一个表中大部分的行,那么我们建议使用VACUUM FULL, 这样该表的稳定态尺寸可以因为VACUUM FULL更富侵略性的方法而显著减小。 日常的磁盘空间清理,请使用 VACUUM,而不是 VACUUM FULL;
    如果您有一个表,它的内容经常被完全删除,那么可以考虑用 TRUNCATE,而不是后面跟着 VACUUM 的 DELETE。 TRUNCATE 立即删除整个表的内容, 而不要求随后的 VACUUM 或者VACUUM FULL 来恢复现在没有用的磁盘空间;

    2.3 更新规划器统计;
    PostgreSQL 的查询规划器依赖一些有关表内容的统计信息用以为查询生成好的规划。 这些统计是通过ANALYZE 命令获得的,您可以直接调用这条命令, 也可以把它当做 VACUUM 里的一个可选步骤来调用。 拥有合理准确的统计是非常重要的,否则,选择了恶劣的规划很可能会降低数据库的性能; 和为了回收空间做清理一样,经常更新统计信息也是对更新频繁的表更有用。 不过,即使是更新非常频繁的表,如果它的数据的统计分布并不经常改变,那么也不需要更新统计信息。 一条简单的拇指定律就是想想表中字段的最大很最小值改变的幅度。 比如,一个包含行更新时间的 timestamp 字段将是随着行的追加和更新稳定增长最大值的; 这样的字段可能需要比那些包含访问网站的 URL 的字段更频繁一些更新统计信息。 那些 URL 字段可能改变得一样频繁,但是其数值的统计分布的改变相对要缓慢得多;
    我们可以在特定的表,甚至是表中特定的字段上运行 ANALYZE, 所以如果您的应用有需求的话,我们是可以对某些信息更新得比其它信息更频繁的。 不过,在实际中,这种做法的实用性是值得怀疑的。
    ANALYZE 是一项相当快的操作,即时在大表上也很快, 因为它使用了统计学上的随机采样的方法进行行采样, 而不是把每一行都读取进来。因此,每隔一段时间对整个数据库运行一便这条命令可能更简单; 注: 尽管用 ANALYZE 按字段进行挖掘的方式可能不是很实用, 但您可能还是会发现值得按字段对 ANALYZE 收集的统计信息的详细级别进行调整。 那些经常在WHERE子句里使用的字段如果有非常不规则的数据分布, 那么就可能需要比其它字段更细致的数据图表.
    参阅 ALTER TABLE SET STATISTICS
    我们对大多数节点都建议在每天的低使用时段安排一次数据库范围的 ANALYZE: 这个任务可以有效地和每天的 VACUUM 组合在一起。 不过,这对那些表统计信息改变相对缓慢的节点可能会过于夸张, 而且少一些的 ANALYZE 也足够了;

    2.4 避免事务 ID 重叠造成的问题;

    PostgreSQL 的 MVCC 事务语意依赖于比较事务 ID(XID)的数值: 一条带有大于当前事务的 XID 的插入 XID 的行版本是"属于未来的", 并且不应为当前事务可见。但是因为事务 ID 的大小有限(在我们写这些的时候是 32 位), 如果一次集群如果运行的时间很长(大于 40亿次事务), 那么它就要受到事务 ID 重叠的折磨:
    XID 计数器回到零位, 然后突然间所有以前的事务就变成看上去是在将来的 — 这意味着它们的输出将变得可见。
    简而言之,可怕的数据丢失,(实际上数据仍然在那里,但是如果您无法获取数据,这么说也只是幸灾乐祸。) 在 PostgreSQL 7.2 之前, 防御 XID 重叠的唯一办法就是至少每40亿事务就重新做一次initdb。 这种做法对高流量的节点而言当然不是令人满意的做法,所以我们设计了更好的方法。 新的方法允许某个服务器仍然保持运行状态,不需要 initdb 或者任何类型的重启。 代价就是下面这样的维护要求: 数据库中的每个表都必须在每十亿次事务中至少清理一次 .

    从实际角度出发,这个要求不算一个很繁重的要求, 但是因为如果我们没能满足这个要求的后果是全部数据的丢失(而不仅仅是磁盘空间的浪费或者性能的下降), 我们制作了一些特殊的东西来帮助数据库管理员避免灾难的发生。

    对于集群中的每个数据库,PostgreSQL 都跟踪自上次全数据库范围 VACUUM 以来的时间。 如果任何数据库接近了十亿次事务的危险级别,系统就开始发出警告信息。 如果什么都不干,那么系统最终会停止正常的操作,直到进行了合适的手工操作。 本节剩下的部分给出这方面的细节。
    XID 比较的新方法剥离出两个特殊的 XID,数字 1 和 2 (BootstrapXID 和 FrozenXID)。 这两个 XID 总是被认为表任何普通的 XID 旧。普通的 XID(那些大于 2 的)使用模-231运算进行比较。 这就意味着对于每个普通的 XID,总是有二十亿个 XID 是"更旧"以及二十亿个 XID"更新"; 表达这个意思的另外一个方法是普通的 XID 空间是没有终点的环。

    对于事务ID,PostgreSQL有三个事务ID有特殊意义:

    • 0代表invalid事务号
    • 1代表bootstrap事务号
    • 2代表frozon事务。frozon transaction id比任何事务都要老

    因此,一旦一条元组带着特定的普通 XID 创建出来,那么该元组 将在以后的二十亿次事务中表现得是"在过去",而不管我们说的是哪个普通 XID。 如果该元组在超过二十亿次事务之后仍然存在, 那么它就会突然变成在将来的元组。为了避免数据丢失, 老的元组必须在到达二十亿次事务的年龄之前的某个时候赋予 XID FrozenXID。 一旦它被赋予了这个特殊的 XID,那么它们在所有普通事务面前表现为 “在过去”,而不管事务 ID 是否重叠, 因此这样的元组直到删除之前都会完好,不管要保存多长时间.这个 XID 的重新赋值是VACUUM 控制的. VACUUM 的正常策略是给任何其普通 XID 有超过十亿次已过去事务行版本重新赋值为 FrozenXID。 这个策略保留了原来的插入 XID 直到该数值不再令人感兴趣为止。 (实际上,大多数行版本将可能在还没有"冻结"之前就完成生存和消亡了)。 在这个策略下,任何表在两次 VACUUM 运行之间的最大的安全间隔是十亿次事务: 如果您等的时间更长,那么最后就可能就会有一条不够老的行版本在重新赋值时变成比二十亿次事务更老, 并因此重叠到了未来 — 也就是说,您失去它了。(当然,它在另外二十亿次事务之后会重新出现,不过那样也无济于事。)

    因为上面的原因,我们需要周期性地运行 VACUUM, 所以很难有哪个表会到十亿次事务还没有清理过。但是,为了帮助管理员确保满足了这个要求, VACUUM 在系统表pg_database 里存储了事务 ID 统计。 尤其是一个数据库的 pg_database 行中的 datfrozenxid 字段在任何数据库范围的 VACUUM 操作(也就是没有声明任何表的VACUUM)之后将会被更新。 这个字段里存储的数值是该 VACUUM 命令使用的冻结终止的 XID。 系统保证在该数据库中所有比这个终止 XID 老的普通 XID 都被 FrozenXID 代替。 检查这个信息的一个便利的方法是执行下面的查询

    SELECT datname, age(datfrozenxid) FROM pg_database;
    
    

    age 字段用于测量从中止 XID 到当前事务的 XID 的数目
    使用了这种标准的冻结策略,对一个刚清理过的数据库而言, age 字段将从十亿处开始。当age到达二十亿次的时候, 数据库必须再次清理以避免事务标识重叠造成的问题。 我们建议的策略是至少每半个十亿次(5亿次)事务 VACUUM 一次数据库, 这样就可以保证足够的安全边界范围.为了帮助满足这条规则, 如果有任何 pg_database 记录显示出超过15亿次事务的 age, 那么每次数据库范围的VACUUM 都会自动发出一条警告,比如:

    play=# VACUUM;
    WARNING:  database "mydb" must be vacuumed within 177009986 transactions
    HINT:  To avoid a database shutdown, execute a full-database VACUUM in "mydb".
    VACUUM
    
    

    如果忽略了上面这样的 VACUUM 信息,如果距离事务 ID 重叠小于 1 千万次, 那么 PostgreSQL 就会在每次事务开始前发出类似上面的警告。 如果这些警告还是被忽略了,那么系统将在距离重叠小于 1 百万次的时候关闭,并且拒绝执行任何新的事务:

    play=# select 2+2;
    ERROR:  database is shut down to avoid wraparound data loss in database "mydb"
    HINT:  Stop the postmaster and use a standalone backend to VACUUM in "mydb".
    
    

    这个 1 百万的事务安全边界留下来用于让管理员在不丢失数据的情况下进行恢复, 方法是手工执行所需要的 VACUUM 命令。不过,因为一旦进入了安全关闭模式,系统就不能再执行命令, 做这件事情的唯一的方法是停止 postmaster,使用一个单独运行的后端来执行 VACUUM。 关闭模式不会强制于独立运行的后端。

    带着 FREEZE 选项的 VACUUM 使用了更大胆的冻结策略: 如果行版本已经老得被所有打开的事务看做是良好的, 那么就都冻结.特别是如果在一个空闲的数据库上运行 VACUUM FREEZE,那么就保证该数据库中所有的行版本都被冻结。 因此,只要该数据库没有其它的变化,那么它就不需要后续的清理以避免事务 ID 重叠问题。 这个技巧被 initdb 用于准备 template0 数据库。 我们也应该用这个方法对所有在 pg_database表里标记着 datallowconn = false的数据库进行初始化, 因为我们还没有任何便利的方法 VACUUM 一个您无法联接的数据库。

    2.5 auto-vacuum 守护进程;

    从 PostgreSQL 8.1 开始,系统带有一个额外的可选服务进程, 叫做 autovacuum 守护进程,它的目的是自动执行 VACUUM 和 ANALYZE 命令。在打开这个选项之后,autovacuum 守护进程将周期性运行并且检查那些有大量插入,更新或者删除元组操作的表。 这些检查使用行级别的统计收集设施;因此,除非把 stats row level和 stats row level设置为 true,否则无法使用 autovacuum 守护。 还有,在为superuser reserved connections选择数值的时候,不要忘记给 autovacuum 进程保留一个槽位。 如果打开了 autovacuum 守护,那么它会每隔 autovacumm natime 秒钟运行一次,并且检查应该处理哪个数据库。 任何临近事务 ID 重叠的数据库都会被立即处理。这个时候,autovacuum 发出一个数据库范围的 VACUUM 调用,如果是模板数据库,则发出 VACUUM FREEZE, 然后终止。如果没有数据库复合这个标准,则选择被上次 autovacuum 处理时间最远的那个数据库。 这种情况下,该数据库里的表被检查,然后根据需要发出独立的 VACUUM 或者 ANALYZE 命令。 对于每个表,用两个条件来判断应该使用哪个操作。 如果上次 VACUUM 之后的过期元组的数量超过了"清理阈值(vacuum threshold)", 那么就清理改表。清理阈值是定义为:

    清理阈值 = 清理基本阈值 + 清理缩放系数 * 元组数
    (vacuum threshold = vacuum base threshold + vacuum scale factor * number of tuples)

    这里的清理基本阈值是 autovacuum_vacuum_threshold, 清理的缩放系数是 autovacuum_vacuum_scale_factor, 元组的数目是 失效的元组数目是从统计收集器里面获取的;这事一个半精确的计数,由每次 UPDATE 和 DELETE 操作更新。 (它只是半精确的是因为在重载下,有些信息可能会丢失。) 为了分析,使用了一个类似的条件:分析阈值,定义为:

    分析阈值 = 分析基本阈值 + 分析缩放系数 * 元组数目
    (analyze threshold = analyze base threshold + analyze scale factor * number of tuples)

    它会和上次 ANALYZE 插入,更新,或者删除的元组总数进行比较。
    缺省的阈值和伸缩系数是从 postgresql.conf 里面取得的, 不过,我们可以以每个表独立设置的方式覆盖它,方法就是在系统表 pg_autovacuum 里输入记录。 如果 pg_autovacuum 里面存在对某个特定表的行,那么就使用它声明的设置; 否则使用全局设置。 除了基本阈值和缩放系数之外,在 pg_autovacuum 里还有三个参数可以为每个表进行设置。

    首先,pg_autovacuum.enabled 可以设置为 false, 让 autovacuum 守护进程完全忽略某个表。这种情况下,autovacuum 只有在为了避免事务 ID 重叠清理整个数据库的时候才会动那个表。另外两个参数,清理开销延迟 (pg_autovacuum.vac_cost_delay)和清理开销限制 (pg_autovacuum.vac_cost_limit), 用于为基于开销的清理延迟特性设置表相关的数值。 如果在 pg_autovacuum 里任何数值设置为负数, 或者在 pg_autovacuum 里就根本没有出现特定表的数据行, 那么使用 postgresql.conf 里面对应的数值。

    目前没有任何制作 pg_autovacuum 记录的支持, 只能手工向该系统表中 INSERT。这个特性将在以后的版本中改进, 并且这个系统表的定义也很有可能会改变。
    3. 经常重建索引;

    有时候我们值得用REINDEX命令周期的重建索引;

    在 PostgreSQL 版本 7.4 之前,我们经常有必要避免"索引膨胀", 因为缺乏在 B-tree 索引内部的空间恢复机制。一个情况是就是索引健字的范围随着时间而变化 — 比如,一个在某个表的时间戳上的索引,随着时间的推移,旧的记录会最终被删除 — 就会导致膨胀,因为那些用于不再使用的键字范围的索引页面不回得到重复使用。 随着时间的推移,索引的尺寸可能会变得比里面的有用的数据大得多。
    从 PostgreSQL 7.4 开始,那些已经完全清空的索引页会得到重复使用。 不过这样仍然会有不充分使用空间的可能:如果一个页面中大多数索引键字被删除,只留下很少的部分呢, 那么该页仍然将被分配。所以,如果使用模式是这样的:每个范围里除了少数键字之外,其他大部分键字最终都被删除; 那么这样也会导致空间的低效使用。膨胀的可能性不是无穷的 — 最差的情况是每个页面至少还有一个键字 — 但是对这样的使用模式,我们可能仍然值得安排周期性的重新索引;
    对于非 B-tree 索引的膨胀可能还没有很好地定量分析。 在使用非 B-tree 索引的时候保持对索引的物理尺寸的监控是个很好的主意;
    还有,对于 B-tree 索引,一个新建立的索引从某种意义上比更新了多次的访问起来要快, 因为在新建立的索引上,逻辑上连接的页面通常物理上也连接在一起。 (这样的考虑目前并不适用于非 B-tree 索引。)仅仅从提高访问速度角度出发, 可能我们也值得周期性的重建索引。
    4. 日志文件维护;
    把数据库服务器的日志输出保存在一个地方是个好主意。 在碰到危险的问题的时候,日志输出是非常宝贵的。 不过,日志输出可能很庞大(特别是在比较高的调试级别上), 而且您不会无休止地保存它们.您需要"旋转"日志文件, 这样生成新的日志文件并且经常抛弃老的; 如果您简单地把postmaster的stderr定向到一个文件中, 您会有日志输出, 但是截断日志文件的唯一的方法是停止并重起postmaster。 这样做对于开发环境中使用 PostgreSQL 可能是可以的,但是您肯定不想在生产环境上这么干; 一个更好的办法是把 postmaster 的 stderr (错误流 ‘standard error’)输出发送到某种日志旋转程序里。 我们有一个内置的日志旋转程序,您可以通过在 postgresql.conf 里设置配置参数 redirect_stderr 为 true 的办法打开它,终端下输入:

    $ sudo vim /etc/postgresql/8.2/main/postgresql.conf
    
    

    找到: #redirect_stderr = off 一项,将#号注掉,然后将off改为on; 另外,您可能会觉得把 postmaster 的stderr 输出给某些日志旋转脚本会更好些,特别是您已经在其它服务器上用了这个程序的时候。 比如,包含在 Apache 发布里的 rotatelogs 工具就可以用于 PostgreSQL。 要这么做,只需要把 postmaster 的 stderr 重定向到指定程序。 如果您用 pg_ctl 启动服务器,那么 stderr 已经重定向到 stdout, 因此您只需要一个管道命令,比如:

    $ pg_ctl start | rotatelogs /var/log/pgsql_log 86400 
    
    

    另外一种生产级的管理日志输出的方法就是把它们发送给 syslog,让 syslog 处理文件旋转。 要利用这个工具,我们需要设置 postgresql.conf 里的 log_destination 配置参数设置为 syslog (记录 syslog 日志)
    终端下输入:

    $ sudo vim /etc/postgresql/8.2/main/postgresql.conf
    
    

    然后修改
    #log_destination = ‘stderr’

    将stderr改为syslog; 然后在您想强迫 syslog 守护进程开始写入一个新日志文件的时候, 您就可以发送一个 SIGHUP 信号给它。 如果您想自动旋转日志文件,那么我们可以配置 logrotate 程序处理 syslog 的日志文件。
    不过,在很多系统上,syslog 不是非常可靠,特别是在大型日志信息的情况下; 它可能在您最需要那些信息的时候截断或者丢弃它们。 还有,在 linux 上,syslog 会把每个消息刷新到磁盘上, 导致很恶劣的性能。 (您可以在 syslog 配置文件里面的文件名开头使用一个 - 来关闭这个行为。)
    请注意上面描述的所有解决方案关注的是在可配置的间隔上开始一个新的日志文件, 它们并没有处理删除旧的,不再需要的日志文件的事情。您可能还需要设置一个批处理,周期地删除旧日志文件。 另外一个可能的解法是配置日志旋转程序,让它周期地覆盖旧的日志文件。
    5. 关于本文;
    本文大部分资料都是参照中文文档,目的是让兄弟们查找方便一些,详细的东西在中文文档都有,多谢各位弟兄们指点 :)
    6. 更新日志;
    7 参考文档;

    《PostgreSQL 8.1 中文文档》
    8. 相关文档;

    《PostgreSQL安装和简单使用》
    《Postgresql备份和恢复------SQL转储篇》
    《PostgreSQL的配置文件及用户权限》
    《PostgreSQL数据库用户认证》

    展开全文
  • PostgreSQL之vacuum学习

    2021-11-01 21:50:34
    文章目录一、vacuum的背景1.1 常见数据库MVCC实现对比二、vacuum工作机制2.1 vacuum2.2 autovacuum 我们常用的关系型数据库有MySQL、Oracle、SQL Server、PostgreSQL等…但是vacuum的概念只有PG数据库有,而且运维过...


    我们常用的关系型数据库有MySQL、Oracle、SQL Server、PostgreSQL等…但是vacuum的概念只有PG数据库有,而且运维过PG数据库的工程师都应该对它很熟悉,vacuum是PG数据库非常关键的一个操作。那么PG数据库的vacuum是用来干什么的?为什么会有vacuum?

    一、vacuum的背景

    1.1 常见数据库MVCC实现对比

    在了解vacuum之前,我们首先要了解数据库很关键的一个特性:多版本并发控制(MVCC),显而易见这个特性就是为了提高数据库并发而设计的,但是不同的数据库实现MVCC的使用了不同的方法:

    • 以Oracle、MySQL为例
      • 这两种数据库是通过undo日志来实现MVCC。
      • 当数据记录被DML修改,将修改前的数据记录在undo log中,客户端可以读取数据时,通过undo log指针进行回滚找到对应可见的版本。
      • 长事物、大事物会导致undo log暴涨,一定程度上会导致系统日志文件磁盘空间占用的暴涨。只有将事物提交/回滚,相关版本记录不再需要时,对应的版本数据才会被清理,undo系统文件空间才会把无效的版本空间进行释放,具体空间释放操作需要看数据库版本以及参数设置。
    • 以SQL Server为例
      • 它是通过tempdb数据库来实现的。
      • 当数据记录被DML修改,将旧版本数据写入tempdb进行存储,客户端读取数据时,可从通过指针找到tempdb数据库中对应可见的版本。
      • 长事物、大事物会导致tempdb空间暴涨,只有事物提交,相关版本记录不再需要时,才会将相关的版本记录进行释放,需要注意的是这部分磁盘空间消耗是没有释放给操作系统的,需要手动进行磁盘空间收缩。
    • 以PostgreSQL为例
      • 它是通过保留变更前的记录来实现MVCC的。
      • 当数据记录被DML修改,旧版本记录仍保留不变,仅仅需要修改相关记录的xmin、xmax属性,并新增写入变更后的版本记录数据。
      • 由于历史版本数据仍然保留在原表空间中,默认情况下autovacuum会按照一定的参数设置策略检测并进行一定的清理,但频繁的数据变极大可能导致旧版本数据空间来不及进行空间回收,从而导致表空间膨胀。

    各MVCC实现方法的优缺点对比:

    • 通过undo log或者tempdb来进行旧版本存储的方式,有效的避免了表空间膨胀,相对于PG直接保留旧版本数据的方式,每次DML操作都需要额外的日志写入,存在一定的IO消耗(目前SSD盘存储下,感觉影响不会很大);
    • PG这种直接保留旧版本数据的方式,无需额外的日志写入的消耗,但是一定程度上会导致旧版本数据没有及时清理,导致表空间膨胀,影响该表数据的查询效率(扫描了不必要的数据页)

    二、vacuum工作机制

    2.1 vacuum

    由于对表记录进行DML后,旧版本数据其实并没有真正的进行物理删除,而是继续保留且进行相应的记录打标,这些不在需要的旧版本记录称为dead tuple。
    vacuum的作用就是回收表膨胀出现的dead tuple,将对应的表空间释放给数据库or操作系统。

    1、命令格式

    VACUUM [ ( option [, ...] ) ] [ table_and_columns [, ...] ]
    VACUUM [ FULL ] [ FREEZE ] [ VERBOSE ] [ ANALYZE ] [ table_and_columns [, ...] ]
    
    where option can be one of:
    
        FULL [ boolean ]
        FREEZE [ boolean ]
        VERBOSE [ boolean ]
        ANALYZE [ boolean ]
        DISABLE_PAGE_SKIPPING [ boolean ]
        SKIP_LOCKED [ boolean ]
        INDEX_CLEANUP [ boolean ]
        TRUNCATE [ boolean ]
        PARALLEL integer
    
    and table_and_columns is:
    
        table_name [ ( column_name [, ...] ) ]
    

    2、vacuum的几种关键变体

    • vacuum full : 执行期间需要获取对应表的独占锁,阻塞其他客户端的读写操作。该模式下会将对应表数据重新写入一个新的表空间文件,最后替换为新的表文件,这种方式下可以回收dead tuple空间并释放给操作系统。该操作执行消耗是比较大的,且耗时的。
    • vacuum freeze : 使用一种激进的方式冻结元祖,相当于把参数 vacuum_freeze_min_age 、 vacuum_freeze_table_age 设置为0。该模式下Full参数指定是多余的,该操作执行消耗同样是比较大的,且耗时的。
    • vacuum verbose : 执行期间不需要获取对应表的独占锁,允许其他客户端的并发读写操作。该模式下仅仅会将dead tuple空间进行回收并释放给数据库,并不会释放给操作系统,vacuum期间打印每张表详细的垃圾回收记录。
    • vacuum analyze : 执行期间不需要获取对应表的独占锁,允许其他客户端的并发读写操作,执行完毕vacuum后会再次执行analyza重新采集相关表的统计信息。该模式下仅仅会将dead tuple空间进行回收并释放给数据库,并不会释放给操作系统。

    3、运维建议

    • vacuum_cost_delay :计算每个毫秒级别所允许消耗的最大IO,vacuum_cost_limit/vacuum_cost_dely。 默认vacuum_cost_delay为20毫秒。
    • vacuum_cost_page_hit :vacuum时,page在buffer中命中时,所花的代价。默认值为1。
    • vacuum_cost_page_miss:vacuum时,page不在buffer中,需要从磁盘中读入时的代价默认为10。
    • vacuum_cost_page_dirty:当vacuum时,修改了clean的page。这说明需要额外的IO去刷脏块到磁盘。默认值为20。
    • vacuum_cost_limit:当超过此值时,vacuum会sleep。默认值为200。

    2.2 autovacuum

    autovacuum为PG数据库中可以实现自动vacuum的一个守护进程,需要数据库将参数autovacuum参数打开。autovacuum会自动检测发生了大量DML操作的表对象,并对其进行垃圾回收和统计信息的重新采集,相当于手动执行 vacuum analyze 。

    1、重点参数

    • autovacuum : 是否开启autovacuum守护进程,默认开启
    • log_autovacuum_min_duration : 指定autovacuum执行耗时超过该参数时,将对应操作记录到日志,-1表示禁用autovacuum的日志记录
    • autovacuum_max_workers : autovacuum可启动的最大worker数,默认为3
    • autovacuum_naptime : 指定两次autovacuum之间的时间延迟,默认为1min
    • autovacuum_vacuum_threshold 、autovacuum_vacuum_scale_factor : 指定一张表Delete、Update的tuple数超过 autovacuum_vacuum_scale_factor * table_size + autovacuum_vacuum_threshold 时,自动触发autovacuum。默认autovacuum_vacuum_threshold为50,autovacuum_vacuum_scale_factor为20
    • autovacuum_vacuum_insert_threshold 、 autovacuum_vacuum_insert_scale_factor : 指定一张表Insert的tuple数超过 autovacuum_vacuum_insert_scale_factor * table_size + autovacuum_vacuum_insert_threshold 时,自动触发autovacuum。默认autovacuum_vacuum_insert_threshold为50,autovacuum_vacuum_insert_scale_factor为20
    • autovacuum_analyze_threshold 、autovacuum_analyze_scale_factor : 指定一张表Insert、Delete、Update的tuple数超过 autovacuum_analyze_scale_factor * table_size + autovacuum_analyze_threshold 时,自动触发analyza操作。默认autovacuum_analyze_threshold为50,autovacuum_analyze_scale_factor为20
    • autovacuum_freeze_max_age : 为防止表中事物ID回卷,指定表的最大事物ID(pg_class.relfrozenxid),超过该参数值自动触发autovacuum,即使autovacuum参数设置为off
    • autovacuum_multixact_freeze_max_age : 为防止表中多个事物ID回卷,指定表的最大事物ID(pg_class.relminmxid),超过该参数值自动触发autovacuum,即使autovacuum参数设置为off
    • autovacuum_vacuum_cost_delay : 指定计算autovacuum的代价延迟值
    • autovacuum_vacuum_cost_limit : 指定autovacuum操作的代价限制值

    2、工作原理

    • 当参数autovacuum设置为on时,数据库会启动一个autovacuum的守护进程,当满足触发条件时启动相关的autovacuum经常进行垃圾回收操作
    • 当表update,delete的tuples数量超过 autovacuum_vacuum_scale_factor * table_size + autovacuum_vacuum_threshold 时,自动触发autovacuum操作
    • 当表insert的tuples数量超过 autovacuum_vacuum_insert_scale_factor * table_size + autovacuum_vacuum_insert_threshold 时,自动触发autovacuum操作
    • 当表的insert,delete,update的tuple超过 autovacuum_analyze_scale_factor * table_size + autovacuum_analyze_threshold 时,自动触发analyza操作
    • 当表的最大事物ID超过autovacuum_freeze_max_age、autovacuum_multixact_freeze_max_age 时,自动触发autovacuum操作
    • 默认两次autovacuum之前的时间间隔为autovacuum_naptime,且每次进行autovacuum时可启动的最大并发数为autovacuum_max_workers

    3、运维建议

    • 全局参数并不一定适用于所有表,特殊表可在表级别定义相关参数。例如变更频繁的表,可适当减少autovacuum_vacuum_scale_factor、autovacuum_vacuum_threshold参数值,使得其可以及时的垃圾回收,避免表膨胀影响其查询效率
    • autovacuum_max_workers可根据操作系统CPU资源进行适当调整
    展开全文
  • PostgreSQL-Vacuum

    2021-07-10 15:27:25
    autovacuum 尽管我们看到autovacuum已经被#注释掉,但是这个功能还是默认开启的,触发条件有两种 第一种:表上(update,delte 记录) >= autovacuum_vacuum_scale_factor* reltuples(表上记录数) +autovacuum_vacuum_...

    Postgresql表中隐藏字段

            -oid: 行的对象标识符,创建表的时候使用了with oid,或者是设置了default_with_oids 配置参数时出现;

            -tableoid:包含本行的表的 OID。

            -xmin:插入该行版本的事务的标识(事务 ID);

            -xmax:删除事务的标识(事务ID),如果不是被删除的行版本,那么是零;

            -cmin:插入事务内部的命令标识,从0开始;

            -cmax:删除事务内部的命令标识,从0开始;

            -ctid:一个行版本在它所处的表内的物理位置。

     Postgresql执行update操作

     MVCC实现

    --ACID要素

            -A:原子性——事务的不可分割性

            -C:一致性——事务的完整性

            -I:隔离性——并发事务的隔离性

            -D:持久性——事务的持久性,WAL机制

    --事务隔离级别

    隔离级别

    脏读

    不可重复读

    幻读

    读未提交(read uncommitted

    读已提交(read committed

    避免

    可重复读(repeatable read

    避免

    避免

    可串行化(serializable

    避免

    避免

    避免

    --MVCC三种实现方式

            -写新数据时,把旧的数据放到一个单独的空间内,如回滚段,其他事务读取时,从回滚段的去读,如oracle&mysq中的innodb引擎。

            -写数据时,把旧的数据放到一个临时表空间,如sql server(tempdb)。

            -写数据时,旧数据不删除,插入新的数据,如postgresql。

    Vacuum的功能

    --回收空间

            -vacuum:删除数据将其所占空间重新置为可用,新数据优先插入这些可用空间;

    执行效率较高并且通过共享锁可以和其他操作并行,对插入会有一定的影响。

            -vacuum full:删除数据时会先将原来可用数据导入一个新的数据文件中,再删除

    原来的数据,同时还要重建索引,整个过程耗时较长,执行效率低,但执行后会对性

    能有很大的提升;整个执行过程通过排他锁保障其他事务均不可访问该表。

    Vacuum异常
        第一种:number of page slots needed (1277312) exceeds max_fsm_pages (819200)
        第二种:relation "XXX" contains more than "max_fsm_pages" pages with useful free space
        第三种:could not read block 512591 of relation 1663/16396/16768: Result too large

    原因分析:fsm(free space map),fsm是记录数据页上有因为vacuum而存在的是空闲空间,方便能够快速的插入数据,而max_fsm_pages是存在一定的上限的,所以这是明显超出上限报错。
    
    处理:
    方法一:vacuum full,尽量选择在低谷期
    方法二:修改max_fsm_pages,max_fsm_relations的值,但是需要重启数据库
         gpconfig -c max_fsm_relations -v 200
         gpconfig -c max_fsm_pages -v 5000

    --冻结tuple的xid-freeze

            PG会在每条记录(tuple)的header中,存放xmin,xmax信息(增删改事务ID)。transactionID的最大值为2的32次,即无符整形来表示。当transactionID超过此最大值后,会循环使用。这会带来一个问题:就是最新事务的transactionID会小于老事务的transactionID。如果这种情况发生后,PG就没有办法按transactionID来区分事务的先后,也没有办法实现MVCC了。因此PG用vacuum后台进程,按一定的周期和算法触发vacuum动作,将过老的tuple的header中的事务ID进行冻结。冻结事务ID,即将事务ID设置为“2”(“0”表示无效事务ID;“1”表示bootstrap,即初始化;“3”表示最小的事务ID)。PG认为被冻结的事务ID比任何事务都要老。这样就不会出现上面的这种情况了。

    注意点:PG在9.4版本以前执行freeze时IO会很高,FROZEN是通过一个等于2的XID来表示的。从9.4开始改成了通过tuple 头部的t_infomask中的两个互斥的比特位来表示HEAP_XMIN_COMMITTED|HEAP_XMIN_INVALID。9.6对这块做了改进,当数据页中的所有记录已经是FROZEN状态时,在发起vacuum freeze时会跳过这个页的扫描,从而大幅提升静态数据的freeze操作,减少IO扫描。xid如果不超过21亿是正常比较,超过21亿的需要取模进行比较,如果行上的t_infomask中HEAP_XMIN_COMMITTED,HEAP_XMIN_INVALID同时存在就会被认为是FrozenTransactionId。

    Freeze异常
      ERROR:  found xmin 2088747257 from before relfrozenxid 2810153180
    原因分析:因为每次freeze之后,在pg_class中都会记录下最后一次的freeze的事务号,该报错信息显示发现一个比表的冻结年龄更早的数据记录。
    Freeze异常处理
        a.如果不是单表无法进行处理,可以查看pg_stat_activity中是否有正在执行尚未提交的长事务,如果存在可以选择继续等待事务执行完毕,或者杀死该事务select pg_terminate_backend(pid)
        b.relfrozenxid 是存储在pg_class,pg会把一些关键系统表的元数据信息存储在relcache中,rd_isnailed=true就是表明这个表的relcache的relcache是不会去进行更新的,关键的系统表一般也不会去进行表元数据的变更,所以系统表不去更新relcache也是正常的。所以问题的根因就是vacuum是读到的relfrozexid来自relcache的,更新catalog中的relfrozexid不会去刷新relcache,导致一直读到的是错误的relfrozexid,所以出现vacuum freeze报错的问题。10.2,9.6.7,9.5.11,9.4.16到修复版本之间的版本的pg实例都会存在相关问题。10.5, 9.6.10, 9.5.14, 9.4.19对这个问题进行了修复。
    修复方式:
        1.重启数据库,重启后会重新读入新数据内容到relcache中,相当于刷新relcache。
        2.删除$PGDATA/global/pg_internal.init,这个文件就是存储的relcache的内容,有新的连接连
    入会创建新的pg_internal.init文件。

    数据库异常

    ERROR:  database is not accepting commands to avoid wraparound data loss in database “mydb"

    HINT:  Stop the postmaster and vacuum that database in single-user mode.

    在👆的报错之前,我们可能会看到👇的警告

    WARNING:  database "mydb" must be vacuumed within 177009986 transactions

    HINT:  To avoid a database shutdown, execute a database-wide VACUUM in "mydb".

    PG中规定:

    当旧的XID达到1000万时,发出警告,忽略警告后,系统将在距离重叠小于100万次的时候关闭,拒绝提供任何新的事务。这个100万的事务安全边界留下来用于让管理员在不丢失数据的情况下进行恢复,方法是手工执行所需要的VACUUM命令。不过,因为一旦进入了安全关闭模式,系统就不能再执行命令,做这件事情的唯一的方法是停止主服务器, 使用单用户模式来执行VACUUM。关闭模式不会强制于单用户模式。

    --更新统计信息

            vacuum analyze时,会更新统计信息,让PG的planner能够算出更准确的执行计划。autovacuum_analyze_threshold和autovacuum_analyze_scale_factor参数可以控制analyze的触发的频率。

    --更新visibility map

            在PG中,有一个visibility map用来标记那些page中是没有dead tuple的。这有两个好处,一是当vacuum进行scan时,直接可以跳过这些page。二是进行index-only scan时,可以先检查下visibility map。这样减少fetch tuple时的可见性判断,从而减少IO操作,提高性能。另外visibility map相对整个relation,还是小很多,可以cache到内存中。

    autovacuum

            尽管我们看到autovacuum已经被#注释掉,但是这个功能还是默认开启的,触发条件有两种

    第一种:表上(update,delte 记录) >= autovacuum_vacuum_scale_factor* reltuples(表上记录数) +autovacuum_vacuum_threshold;

    第二种:指定表上事务的最大年龄配置参数autovacuum_freeze_max_age,默认为2亿,达到这个阀值将触发 autovacuum进程,从而避免 wraparound。

    autovacuum查询执行记录

    select schemaname,relname,last_autovacuum,last_autoanalyze from pg_stat_all_tables;

    autovacuum无法启动异常

            正常情况下,通过ps -ef | grep auto可以看到autovacuum处在运行的过程中过,但是也有些情况无法正常启动,检查配置autovacuum=on处于开启状态,同时日志中会出现类似一下情况:

    11:14:15 CST,,0,LOG,00000,"could not resolve ""localhost"": Temporary failure in name resolution”,,,,,,,,,”"
    11:14:15 CST,,0,LOG,00000,"disabling statistics collector for lack of working socket”,,,,,,,,,”"
    11:14:15 CST,,0,WARNING,01000,"autovacuum not started because of misconfiguration",,"Enable the ""track_counts"" option.",,,,,,,""

            通过日志我们可以看到貌似是track_counts参数没有打开,show track_counts;显示该参数确实处于off状态,但是postgresql.conf显示该参数on,在往上可以看到"could not resolve“ ”localhost"";查询auto vacuum文档,发现该功能气功需要以下3个条件:

    (1)autovacuum = on

    (2)track_counts = on

    (3)/etc/hosts #能 ping通 localhost

    所以查看一下,/etc/hosts文件127.0.0.1是否存在或者被注释,修改使其生效重启数据库即可。

    autovacuum占用CPU过高问题处理

            如上图在autovacuum中可能会偶出现CPU变的异常高的情况,在其官方文档中有这么一段解释:

            Vacuuming (whether automatic or manual) stops at the oldest transaction id that is still in use. Otherwise it would be vacuuming active transactions, which is not sensible at all.

            简而言之,长事务会导致vacuum进程一直处于运行状态,并且会占据很高的CPU;所以在设置autovacuum时一定要注意选择规避可能出现长事务的时间,选择系统较为空闲的时间。                        

            autovacuum可以直接使用pg_terminate_backend() 的方式直接kill该进程,它会自动重启。

    展开全文
  • PostgreSQL中的VACUUM

    2021-04-15 09:04:18
    最近搞了一个公众号PostgreSQL运维技术,欢迎来踩~ 悄悄放一张: PostgreSQL运维技术 ...为了删除死亡元组,VACUUM提供了两种模式,即Concurrent Vacuum和Full Vacuum。 Concurrent Vacuum通常简称为VACUUM。...

    最近搞了一个公众号PostgreSQL运维技术,欢迎来踩~

    悄悄放一张:

    PostgreSQL运维技术 

     

    我在之前的一篇介绍MVCC的文章中提到,MVCC有事务ID回卷的问题,它的解决方案是VACUUM。但是没有展开讲。这章的话,会详细地介绍下VACUUM。

    VACUUM的两个主要任务是删除死亡元组和冻结事务ID

    为了删除死亡元组,VACUUM提供了两种模式,即Concurrent Vacuum和Full Vacuum

    Concurrent Vacuum通常简称为VACUUM。它在删除表文件中的死亡元组时,其他事务仍可以在此进程运行时读取表。而Full VACUUM在运行时其他事务不能访问表。

     

    本章将主要描述以下内容

    VM(可见性映射)

    Freeze

    删除不必要的clog

    AutoVacuum

    Full VACUUM

     

     

    注:本文是The Internals of PostgreSQL第六章


     

    6.1. VACUUM的概述

     

    VACUUM对数据库中的表执行以下的任务:

    1、删除死亡元组

        删除死亡元组和整理每个页面的活元组。

        删除指向死元组的索引元组。

    2、冻结old txids

        如有必要,冻结元组的old txids。

        更新冻结的txid相关的系统目录(pg_database和pg_class)。

        如果可能,清除clog不必要的部分。

    3、其他

        更新已处理表的FSM和VM。

        更新一些统计信息(pg_stat_all_tables等)。

     

    下面的伪代码描述了VACUUM处理。

    
    (1)  FOR each table
    (2)       Acquire ShareUpdateExclusiveLock lock for the target table
    
              /* The first block */
    (3)       Scan all pages to get all dead tuples, and freeze old tuples if necessary 
    (4)       Remove the index tuples that point to the respective dead tuples if exists
    
              /* The second block */
    (5)       FOR each page of the table
    (6)            Remove the dead tuples, and Reallocate the live tuples in the page
    (7)            Update FSM and VM
               END FOR
    
              /* The third block */
    (8)       Clean up indexes
    (9)       Truncate the last page if possible
    (10       Update both the statistics and system catalogs of the target table
               Release ShareUpdateExclusiveLock lock
           END FOR
    
            /* Post-processing */
    (11)  Update statistics and system catalogs
    (12)  Remove both unnecessary files and pages of the clog if possible


     

    (1)从指定的表中获取每个表。

    (2)获取表的ShareUpdateExclusiveLock锁。这个锁允许读取其他事务

    (3)扫描所有页面得到所有死元组,如果有必要冻结旧元组。

    (4)删除指向各自死亡元组的索引元组(如果存在的话)。

    (5)对表格的每一页,执行以下步骤(6)和(7)。

    (6)移除死去的元组,在页面中重新分配活着的元组。

    (7)更新目标表中的FSM和VM。

    (8)使用index_vacuum_cleanup()@indexam.c函数清理索引。

    (9)截断最后一页,如果最后一页没有任何元组。

    (10)更新目标表中与vacuum处理相关的统计信息和系统目录。

    (11)更新与真空处理相关的统计数据和系统目录。

    (12)如果可能,删除clog中不必要的文件和页面。

     

    这个伪代码有两个部分:每个表的循环和后续处理。内环可分为三个区块。每个块都有单独的任务。

    下面将概述这三个模块和后期处理。

     

    注意:VACUUM命令从版本13开始就支持PARALLEL选项,如果设置了该选项,并且创建了多个索引,那么它将并行地处理vacuum index和cleanup index 阶段。

    注意,此特性仅在VACUUM命令中有效,autovacuum不支持此特性。

     

    6.1.1. 第一部分

     

    这一部分执行冻结处理并删除指向死元组的索引元组。

     

    首先,PostgreSQL扫描一个目标表,建立一个死元组列表,如果可能的话,冻结旧元组。列表存储在本地内存的maintenance_work_mem中。

     

    扫描完成后,PostgreSQL通过引用死元组列表来删除索引元组。这个过程在内部被称为“清理阶段”。无须多说,这个过程是昂贵的。在版本10或更早的版本中,清理阶段是一定会被执行的。在版本11或更高版本中,如果目标索引是B-tree,那么是否执行清理阶段由配置参数vacuum_cleanup_index_scale_factor决定。详细信息请参见对该参数的描述。

    当maintenance_work_mem已满且扫描未完成时,PostgreSQL继续执行下一个任务,即步骤(4)到(7);然后返回步骤(3),继续进行剩余的扫描。

     

     

    6.1.2. 第二部分

     

    这一部分执行删除死元组,并逐页更新FSM和VM。图6.1给出了一个例子:

     

    图. 6.1. 删除死亡元组

    图片

    假设该表包含三个页面。我们关注第0页(即第一页)。这个页面有三个元组。Tuple_2是一个死元组(图6.1(1))。在这种情况下,PostgreSQL移除Tuple_2并重新排序剩下的元组来修复碎片,然后更新FSM和VM(图6.1(2))。PostgreSQL将继续这个过程直到最后一页。

     

    请注意,不必要的行指针不会被删除,它们将在将来被重用。因为,如果删除了行指针,那么关联索引的所有索引元组都必须更新。

     

    6.1.3. 第三部分

     

    第三部分在删除索引后执行清理,并更新与每个目标表vacuum处理相关的统计信息和系统目录。

    而且,如果最后一页没有元组,它将从表文件中截断。

     

    6.1.4. 后续处理

     

    当vacuum处理完成后,PostgreSQL会更新一些与vacuum处理相关的统计信息和系统目录,并尽可能删除不必要的clog(章节6.4)。

     

    注:

    VACUUM采用第8.5节所述的ring buffer;因此,已处理的页面不会缓存在共享缓冲区(shared buffer)中。

     


     

    6.2. VM(可见性映射)

     

    VACUUM处理成本很高;因此,在8.4版本中引入VM以减少此成本。

     

    VM的基本概念很简单: 每个表都有一个单独的可见性映射,它保存表文件中每个页面的可见性。页面的可见性决定了每个页面是否有死元组。真空处理可以跳过没有死元组的页面。

     

    VM的使用情况如图6.2所示。假设该表由三个页面组成,第0页和第2页包含死元组,第1页不包含。该表的VM保存有关哪些页包含死元组的信息。此时,vacuum处理跳过第1页,直接参考VM的信息进行处理。

    图. 6.2. VM是怎么工作的?

     

    每个VM由一个或多个8 KB的页面组成,该文件以“VM”后缀存储。以relfilenode为18751的表文件为例,其中FSM (18751_fsm)和VM (18751_vm)文件如下所示。​​​​​​​

     $ cd $PGDATA$ ls -la base/16384/18751*-rw------- 1 postgres postgres  8192 Apr 21 10:21 base/16384/18751-rw------- 1 postgres postgres 24576 Apr 21 10:18 base/16384/18751_fsm-rw------- 1 postgres postgres  8192 Apr 21 10:18 base/16384/18751_vm

     

    6.2.1. VM的增强版

     

    在9.6版本中增强了VM,以提高冻结处理的效率。新的VM显示了页面的可见性以及元组是否在每个页面中被冻结的信息(章节6.3.3)。

     


     

    6.3. Freeze处理

     

    冻结处理有两种模式,根据特定条件在任意一种模式下执行。为了方便起见,这些模式被称为Lazy(惰性)模式和eager(急切)模式。

    注:concurrent Vacuum通常被称为“lazy Vacuum”。然而,本文档中定义的lazy模式是冻结处理执行的一种模式。

    冻结处理通常在lazy模式下运行;但是,在满足特定条件时运行eager模式。

    在lazy模式下,冻结处理只扫描使用目标表的VM各自包含死元组的页面。

    相反, eager模式扫描所有页面,而不管每个页面是否包含死元组,它还更新与冻结处理相关的系统目录,并在可能的情况下删除clog中的不必要部分。

     

    第6.3.1节和第6.3.2节分别描述了这两个模式。以eager模式改进冻结流程,请参见6.3.3。

     

    6.3.1. Lazy 模式

     

    当启动freeze处理时,PostgreSQL会计算一个freezeLimit txid值,冻结t_xmin小于这个值的元组。

    freezeLimit txid的定义如下:​​​​​​​

    freezeLimit_txid=(OldestXmin−vacuum_freeze_min_age)
    

     

    OldestXmin是当前运行的事务中最古老的txid。举个例子,如果在执行VACUUM命令时运行三个事务(txids 100、101和102),那么OldestXmin是100。

    而vacuum_freeze_min_age是一个配置参数(默认为50,000,000)。

    图6.3显示了一个特定的示例。这里,Table_1由三个页面组成,每个页面有三个元组。当执行VACUUM命令时,当前txid为50,002,500,并且没有其他事务。在这种情况下,OldestXmin是50002500,因此,freezeLimit txid为2500。冻结处理如下所示。

     

    图. 6.3. Lazy Mode

    图片

     

    第0页: 冻结三个元组是因为所有t_xmin值都小于freezeLimit txid。另外,在这个VACUUM过程中,Tuple_1会因为都是死元组而被移除。

    第1页: 此页因为VM而略过。

    第2页: Tuple_7和Tuple_8冻结;Tuple_7被移除。

    在完成VACUUM处理之前,与VACUUM相关的统计信息会被更新,例如:pg_stat_all_tables' n_live_tup, n_dead_tup, last_vacuum, vacuum_count等。

     

    6.3.2. Eager 模式

     

    eager模式弥补了lazy模式的缺陷。它扫描所有页面,以检查表中的所有元组,更新相关的系统目录,并删除不必要的文件和页面阻塞,如果可能的话。

    当满足以下条件时,将执行eager模式:​​​​​​​

    pg_database.datfrozenxid < (OldestXmin −vacuum_freeze_table_age)
    

    在上面的条件中,pg_database.datfrozenxid表示pg_database系统目录的列,并保存每个数据库最古老的冻结txid。细节在后面描述;因此,我们pg_database.datfrozenxid的值是1821(这是9.5版新数据库集群安装后的初始值)。Vacuum_freeze_table_age是一个配置参数(默认为150,000,000)。

    图6.4显示了一个具体的例子。在Table_1中,Tuple_1和Tuple_7都被移除。Tuple_10和Tuple_11已经插入到第二页。当执行VACUUM命令时,当前txid为150,002,000,并且不存在其他事务。因此,OldestXmin为150,002,000,而freezeLimit txid为100,002,000。在这种情况下,上述条件得到满足,因为:

    1821<(150002000−150000000)

    因此,冻结处理以eager模式执行,如下所示。

    (请注意,这是9.5或更早版本的行为;最新的行为将在章节6.3.3中描述。)

    图6.4. 以eager模式冻结旧元组(9.5版或更早版本)。

    图片

     

    第0页:

    即使所有元组已经冻结,Tuple_2和Tuple_3仍会被检查,

    第1页:

    因为所有的t_xmin值都小于freezeLimit txid,所以该页中的三个元组已经被冻结。注意,该页面在惰性模式下被跳过。

    第2页:

    Tuple_10被冻结。Tuple_11没有。

     

    在冻结每个表之后,目标表的pg_class.relfrozenxid被更新。pg_class是一个系统目录,每个pg_class.relfrozenxid保存对应表的最新冻结xid。在这个例子中,Table_1的pg_class。relfrozenxid被更新为当前的freezeLimit txid(即100,002,000),这意味着所有在Table_1中t_xmin小于100,002,000的元组都被冻结。

    在完成VACUUM之前,pg_database.datafronzenxid也可能会被更新。每个pg_database.datfrozenxid列保存着相应数据库里最小的pg_class.relfrozenxid。

    例如,如果只有Table_1在eager模式下被冻结,那么pg_database.datfrozenxid不会被更新。因为这个数据库中其他的表的pg_class.relfrozenxid还没有被更新。如果数据库中的所有表都以eager 模式冻结,那么pg_database.datfrozenxid会被更新。

     

    Freeze命令的可选项

    带有冻结选项的VACUUM命令将强制冻结指定表中的所有txids。这是在eager模式下执行的;但是,freezeLimit被设置为OldestXmin(而不是' OldestXmin - vacuum_freeze_min_age ')。例如,当txid 5000执行VACUUM FULL命令时,没有其他正在运行的事务,OldesXmin将设置为5000,小于5000的txid将被冻结。

     

    6.3.3. 改进eager模式下的Freeze处理

     

    9.5版本或更早版本中的eager模式效率不高,因为它总是扫描所有页面。例如,在第6.3.2节的示例中,即使第0页中的所有元组都被冻结,仍然会扫描第0页。

    为了解决这个问题,9.6版本改进了VM和冻结进程。如6.2.1节所述,VM有关于是否所有元组在每个页面中都被冻结的信息。当以eager模式执行冻结处理时,可以跳过只包含冻结元组的页面。

    图6.6显示了一个示例。冻结该表时,根据VM的具体信息跳过第0页。冻结第一页后,由于该页的所有元组都已冻结,关联的VM信息会更新。

    图6.6. 在eager模式下冻结旧元组(9.6或更高版本)。

     


     

    6.4. 删除不必要的Clog文件

     

    在5.4节中描述的clog存储事务状态。当pg_database.datfrozenxid更新后,PostgreSQL尝试删除不必要的clog文件。请注意,相应的clog页面也被删除。

    图6.7显示了一个示例。如果最小的pg_database.datfrozenxid包含在阻塞文件“0002”中,可以删除较旧的文件(“0000”和“0001”),因为存储在这些文件中的所有事务都可以作为整个数据库集群中冻结的txid处理。

    图. 6.7. 删除不必要的clog文件

    图片

     


     

    6.5. Autovacuum

     

    VACUUM已经通过autovacuum守护进程实现了自动化;因此,PostgreSQL的操作变得非常简单。

    autovacuum守护进程定期调用几个autovacuum_worker进程。默认情况下,它每1分钟唤醒一次(由autovacuum_naptime定义),并调用三个worker(由autovacuum_max_works定义)。

    由autovacuum调用的autovacuum工作器对各个表并行地逐步执行VACUUM处理,而对数据库活动的影响最小。

     


     

    6.6. Full VACUUM

     

    虽然并行VACUUM对操作是必要的,但它是不够的。例如,即使删除了许多无用的元组,它也不能减少表的大小。

    图6.8展示了一个极端的例子。假设一个表包含3个页面,每个页面包含6个元组。使用DELETE命令删除元组,使用VACUUM命令删除死元组:

    图. 6.8. 一个展示(并行)VACUUM缺点的例子。

    图片

     

    死去的元组被移除;然而,表的大小并没有减少。这不仅浪费磁盘空间,而且对数据库性能有负面影响。例如,在上面的示例中,当读取表中的三个元组时,必须从磁盘加载三个页面。

    为了处理这种情况,PostgreSQL提供了FULL VACUUM模式。图6.9显示了这种模式的轮廓。

     

    图. 6.9. Full VACUUM 模式的轮廓.

    图片

     

    (1)创建新表文件:图6.9(1)

    当对表执行VACUUM FULL命令时,PostgreSQL首先获取表的AccessExclusiveLock锁,并创建一个大小为8 KB的新表文件。AccessExclusiveLock锁不允许访问。

    (2)复制活元组到新表:图6.9(2)

    PostgreSQL只将旧表文件中的活元组复制到新表中。

    (3)删除旧文件,重建索引,更新statistics, FSM, VM:图6.9(3)

    复制完所有的活元组后,PostgreSQL删除旧文件,重建所有相关的表索引,更新该表的FSM和VM,更新相关的统计信息和系统目录。

    FULL VACUUM的伪代码如下图所示:​​​​​​​

    (1)  FOR each table(2)       Acquire AccessExclusiveLock lock for the table(3)       Create a new table file(4)       FOR each live tuple in the old table(5)            Copy the live tuple to the new table file(6)            Freeze the tuple IF necessary            END FOR(7)        Remove the old table file(8)        Rebuild all indexes(9)        Update FSM and VM(10)      Update statistics            Release AccessExclusiveLock lock       END FOR(11)  Remove unnecessary clog files and pages if possible
    

    使用VACUUM FULL命令时应该考虑两点。

    • 当执行FULL VACUUM处理时,没有人可以访问(读/写)表(阻塞读写)。

    • 临时使用的磁盘空间最多为表的两倍;因此,在处理大表时,有必要检查剩余磁盘容量。

    展开全文
  • L2SI-真空库 真空库为体系结构文档中的所有设备实现了所需的功能并进行了互锁。 每个设备都实现了数据和逻辑的封装,从而使本地功能,变量和IO保持良好的隐藏状态,并且不受外部修改的影响。 该库由多个模块(即...
  • vacuum freeze

    2021-01-27 14:47:51
    背景 PostgreSQL 目前默认的存储引擎,事务可见性需要依赖行头的事务号,...对全表进行FREEZE操作时,会扫描整表,将大于指定阈值least(autovacuum_freeze_min_age, 表级参数vacuum_freeze_min_age)年龄的记录设置为f
  • vacuum-im:跨平台XMPP客户端
  • Vacuum-Cleaner-Agent:C ++中的智能代理简介
  • 小米罗伯洛克真空桥 小米/ Roborock吸尘器的Homebridge插件 这个插件可让您控制Apple Home App(HomeKit)中的Xiaomi真空机器人。 由于Apple不正式支持Homekit中的Vacuums(我们等不及这一刻到来),因此目前以风扇...
  • 先看3个参数: #如果表的事务ID年龄大于该值, 则数据库触发freeze,即使未开启...vacuum_freeze_min_age | 10 #在手动垃圾回收时, 如果表的事务ID年龄大于该值, 将触发FREEZE. 该参数的上限值为 %95 autovacuum_fr
  • Vacuum使用心得

    千次阅读 2018-11-05 17:40:37
    最近在优化PG,在vacuum过程中发现了 (to prevent wrap)。于是花了一周实践深入了解并实践了一把。下面把这一周的心得分享一下,以备遇到同样情况的 朋友以及将来的自己 使用。   数据库总是不断地在执行删除...
  • 地毯增添了家庭的美感,营造出温馨舒适的氛围。这里的真空吸尘器会有很大的帮助 地毯增添了家居的美感,并营造出温馨舒适的氛围。 但是为了保持其外观,定期吸尘和清洁是不可忽视的必要条件。 覆盖房屋地板的地毯...
  • 大电流真空电弧阴极斑点运动的仿真研究,贾申利,宋晓川,本文对大电流真空电弧阴极斑点的运动进行了数值仿真研究。横向磁场用ANSYS计算,计算中考虑电极触头片中的电流分布的影响。首先,�
  • 白菜热质传递数学模型及实验研究,阚安康,韩厚德,以柱状蔬菜白菜研究对象,建立热质迁移数学模型,并采用实验的方法验证了,在设定真空压力状况下,真空室内的压力变化,白菜自身
  • vacuum 初步使用

    千次阅读 2018-08-07 10:00:16
    postgres=# vacuum verbose tmp_t0; INFO: vacuuming "public.tmp_t0" INFO: "tmp_t0": removed 1780975 row versions in 155570 pages INFO: "tmp_t0": found 1780975 removable, 5930272 nonremovable row ...
  • 摘要:本文主要介绍如何进行正常的VACUUM FULL 维护,及时释放磁盘存储。 1、背景 目前根据某项目情况,其DWS的磁盘IO性能低、库内数据量大、对象多、数据膨胀严重。若毫无目的性的进行空间释放,一方面对IO压力很...
  • jcca31a 的数据只有几千条,但是占用了11G的磁盘空间,手动vacuum命令会报这个错 VACUUM jcca31a WARNING: oldest xmin is far in the past HINT: Close open transactions soon to avoid wraparound problems....
  • Postgresql vacuum最佳实践

    千次阅读 2019-08-02 12:24:03
    但其实它也并不完美,说到postgres,不得不提那个让人一直头疼的问题,也是数据库使用者锁诟病最多的地方:vacuum。那么为什么会有vacuum这个东西呢?它是做什么用的呢? 我们先来聊聊postgresql的mvcc机制,我们...
  • PostgreSQL的vacuum流程

    2021-08-24 11:08:10
    vacuum是一种维护过程,有助于PostgreSQL的持久运行,它的两个主要任务是删除死元组,以及冻结事务标识。 vacuum的作用: 1.释放,再利用更新/删除的行所占据的磁盘空间。 2.更新postgresql查询计划中使用的统计数据...
  • Postgres中国技术大会2018(大象汇,第8届)16日主会场 PPT **主要章节:**
  • 通过限制一次性完成的工作量(默认设置为200)来实现限流,每次清理工作完成这么多工作(计数达到autovacuum_vacuum_cost_limit ),它就会休眠20毫秒: autovacuum_vacuum_cost_delay = 20ms autovacuum_vacuum_cost_...
  • PostgreSQL10基础(6)Analyze和Vacuum

    千次阅读 2020-03-02 15:37:37
    参考文档 https://www.postgresql.org/docs/10/sql-analyze.html ...https://www.postgresql.org/docs/10/sql-vacuum.html https://www.postgresql.org/docs/...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 11,998
精华内容 4,799
关键字:

vacuum