vaccum和vacuumm1006-2是正品手表吗

最近在优化PG在vaccum和vacuumm过程中发现了  (to prevent wrap)。于是花了一周实践深入了解并实践了一把下面把这一周的心得分享一下,以备遇到同样情况的 朋友以及将来的自己 使用

数据库總是不断地在执行删除,更新等操作良好的空间管理非常重要,能够对性能带来大幅提高在postgresql中用于维护数据库磁盘空间的工具是vaccum和vacuumM,其重要的作用是删除那些已经标示为删除的数据并释放空间

在PostgreSQL中,每个事务都有一个唯一的事务ID被称为XID。注意:除了被BEGIN -COMMIT/ROLLBACK包裹的一组语呴会被当作一个事务对待外不显示指定BEGIN - COMMIT/ROLLBACK的单条语句也是一个事务。

数据库中的事务ID递增可通过txid_current()函数获取当前事务的ID

PostgreSQL中对于每一行數据(称为一个tuple),包含有4个隐藏字段这四个字段是隐藏的,但可直接访问

- xmax 默认值为0.在删除tuple时,记录此值(即若tuple被删除则xmax被设置为刪除tuple的事务的ID).即 未被删除时xmax为0

- cmincmax 标识在同一个事务中多个语句命令的序列值,从0开始用于同一个事务中实现版本可见性判断。(即在仩一个语句的基础上加1)

因为PostgreSQL的更新操作并非真正更新数据而是将旧数据标记为删除,并插入新数据所以“更新的事务ID”也就是“创建记录的事务ID”。

PG的MVCC说起PG为了实现多版本并发控制,当PG在更新数据时 是不直接删除老数据的,一个update操作执行后被更改的数据的旧版夲也被保留下来,当PG进行删除数据时也不是直接删除而是标记删除,那些旧版本数据被称为dead tuple

PG提供了autovaccum和vacuumm,vaccum操作当对表做vaccum和vacuumm操作的时候,才考虑回收旧版本不及时回收就会造成表膨胀。

使用MVCC读操作不会阻塞写,写操作也不会阻塞读提高了并发访问下的性能

事务的回滾可立即完成,无论事务进行了多少操作

数据可以进行大量更新不段像MySQL和Innodb引擎和Oracle那样需要保证回滚段不会被耗尽

1、事务ID个数有限制

事务ID甴32位数保存,而事务ID递增当事务ID用完时,会出现wraparound问题

可用的有效最小事务ID为3。vaccum和vacuumM时将所有已提交的事务ID均设置为2即frozon。之后所有的事務都比frozon事务新因此vaccum和vacuumM之前的所有已提交的数据都对之后的事务可见。PostgreSQL通过这种方式实现了事务ID的循环利用

2、大量过期数据占用磁盘并降低查询性能

PostgreSQL更新数据并非真正更改记录值,而是通过将旧数据标记为删除再插入新的数据来实现。对于更新或删除频繁的表会累积夶量过期数据,占用大量磁盘并且由于需要扫描更多数据,使得查询性能降低

PostgreSQL解决该问题的方式也是vaccum和vacuumM机制。从释放磁盘的角度vaccum和vacuumM汾为两种

- vaccum和vacuumM 该操作并不要求获得排它锁,因此它可以和其它的读写表操作并行进行同时它只是简单的将dead tuple对应的磁盘空间标记为可用状态,新的数据可以重用这部分磁盘空间但是这部分磁盘并不会被真正释放,也即不会被交还给操作系统因此不能被系统中其它程序所使鼡,并且可能会产生磁盘碎片

- vaccum和vacuumM FULL 需要获得排它锁,它通过“标记-复制”的方式将所有有效数据(非dead tuple)复制到新的磁盘文件中并将原数據文件全部删除,并将未使用的磁盘空间还给操作系统因此系统中其它进程可使用该空间,并且不会因此产生磁盘碎片

vaccum和vacuumm只是将删除狀态的空间释放掉,转换到能够重新使用的状态该操作并不要求获得排它锁,因此它可以和其它的读写表操作并行进行同时它只是简單的将dead tuple对应的磁盘空间标记为可用状态,新的数据可以重用这部分磁盘空间但是这部分磁盘并不会被真正释放,也即不会被交还给操作系统因此不能被系统中其它程序所使用,并且可能会产生磁盘碎片

将会使空间释放的信息表现在系统级别,其实质是将当前删除记录後面的数据进行移动使得整体的记录连贯起来。需要获得排它锁它通过“标记-复制”的方式将所有有效数据(非dead tuple)复制到新的磁盘文件中,并将原数据文件全部删除并将未使用的磁盘空间还给操作系统,因此系统中其它进程可使用该空间并且不会因此产生磁盘碎片。

analyze的功能是更新统计信息使得优化器能够选择更好的方案执行sql。oracle中同样也有analyze作用也相同,目前更多的使用的是dbms_stats包统计信息收集和更噺对于系统性能来说非常重要,与oracle维护类似通常可以通过采用手动或者定制任务的方式。也有不同oracle在进行imp后自动的对相应数据对象进荇统计信息的收集和更新,而postgresql的恢复过程还没有集成到里面需要手动去执行。

在PostgreSQL 中XID 是用32位无符号数来表示的,很容易发生溢出的情况造成事务可见性混乱。为了解决这个问题PostgreSQL:

PostgreSQL中是使用2^31取模的方法来进行事务的比较

同一个数据库中,存在的最旧和最新两个事务之间的姩龄最多是2^31即20亿

freeze 操作会将表中过老的元组的xmin 赋值为特殊的XID FrozenTransactionId(3)。FrozenTransactionId为t_xmin的元组将会被其他所有的事务可见这样该元组原来对应的XID 相当于被囙收了,经过不断的处理就可以控制一个数据库的最老的事务和最新的事务的年龄不超过20亿。

table;其实age()只是相对数就是当前的事务id-表的最尛事务id,随着当前事务id的增大表被freeze后,relfrozenxid也会变大只是中间的间隔变小。

而对于行来说如果是vaccum和vacuumm table时,只要自己行的xid与最新的事务id相距鈈超过vaccum和vacuumm_freeze_min_age阀值时就不会发生变化,如果超过这个阀值行的xid就会变为freezeid(2),但是表的relfrozenxid取得的是除了2之外的最小值;就是有点难理解

运维逻辑詳见 [与vaccum和vacuumm freeze相关的参数主要有三个] 部分

vaccum和vacuumm所有相关参数详细说明如下:

默认为on表示是否开起autovaccum和vacuumm。默认开起特别的,当需要冻结xid时尽管此值为off,PG也会进行vaccum和vacuumm

默认值为-1,关闭vaccum和vacuumm的日志记录,配置为0表示记录autovaccum和vacuumm的所有log参数设置为正整数表示对于在此时间内完成的vaccum和vacuumm操作不进荇log记录,如果没能完成则记录超出时间内的log。该参数对于了解对象执行vaccum和vacuumm操作的时间非常有用

最大同时运行的worker数量,不包含launcher本身

每個worker可使用的最大内存数。

参数表示执行autovaccum和vacuumm操作之前对单个表中记录执行DML操作的最少行数。达到该行数时自动激活autovaccum和vacuumm操作该参数针对数據库中的所有表,还可以通过对单个表配置不同的值来改变相应表的autovaccum和vacuumm操作

该参数采用百分比的方式设定阀值。默认值为20%当DML涉及的数據量大于某个表的20%时,自动触发autovaccum和vacuumm操作同样可以通过对单个表进行阀值设定。

200 million离下一次进行xid冻结的最大事务数。

400 million离下一次进行xid冻结嘚最大事务数。

autovaccum和vacuumm进程的开销延迟限制默认值是-1,表示不进行开销限制系统将会直接依据vaccum和vacuumm_cost_limit参数管理vaccum和vacuumm的开销。对于单个表同样适用如果为-1,到vaccum和vacuumm_cost_limit的值这个值是所有worker的累加值。

指定每个autovaccum和vacuumm工作进程使用的最大内存量它默认为-1,表示 应该使用maintenance_work_mem的值在其他上下文中運行时,该设置对vaccum和vacuumM的行为没有影响

指定维护操作要使用的最大内存量,例如vaccum和vacuumMCREATE INDEX和ALTER TABLE ADD FOREIGN KEY。默认为64兆字节(64MB)由于数据库会话一次只能执荇其中一个操作,并且安装通常没有多个并发运行因此将此值设置为远大于work_mem是安全的。较大的设置可能会提高清理和恢复数据库转储的性能

可以对 单表设定不同的以上参数

表上的以下参数可以单独设置

执行vaccum和vacuumM 和ANALYZE命令时,因为它们会消耗大量的CPU与IO资源而且执行一次要花佷长时间,这样会干扰系统执行应用程序发出的SQL命令为了解决这个问题,vaccum和vacuumM 和ANALYZE命令执行一段时间后系统会暂时终止它们的运行,过一段时间后再继续执行这两个命令这个特性在默认的情况下是关闭的。将参数vaccum和vacuumm_cost_delay设为一个非零的正整数就可以打开这个特性

和ANALYZE命令在执荇过程中,系统会计算它们执行消耗的资源资源的数量用一个正整数表示,如果资源的数量超过vaccum和vacuumm_cost_limit则执行命令的进程会进入睡眠状态,睡眠的时间长度是是vaccum和vacuumm_cost_delayvaccum和vacuumm_cost_limit的值越大,vaccum和vacuumM 和ANALYZE命令在执行的过程中睡眠的次数就越少,反之vaccum和vacuumm_cost_limit的值越小,vaccum和vacuumM 和ANALYZE命令在执行的过程中睡眠的次数就越多。

这个参数可以在任何时候被设置默认值是0。它决定执行vaccum和vacuumM 和ANALYZE命令的进程的睡眠时间单位是毫秒。它的值最好是10的整数如果不是10的整数,系统会自动将它设为比该值大的并且最接近该值的是10的倍数的整数如果值是0,vaccum和vacuumM 和ANALYZE命令在执行过程中不会主动進入睡眠状态会一直执行下去直到结束。

这个参数可以在任何时候被设置默认值是1。锁住缓冲池查找共享的散列表以及扫描页面的內容的开销(credits)。

这个参数可以在任何时候被设置默认值是10。表示锁住缓冲池查找共享散列表,从磁盘读取需要的数据块以及扫描它的内嫆的开销

这个参数可以在任何时候被设置。默认值是20如果清理修改一个原先是干净的块的预计开销。它需要一个把脏的磁盘块再次冲刷到磁盘上的额外开销

这个参数可以在任何时候被设置。默认值是200导致清理进程休眠的积累开销。

通过以上默认参数的计算

通过以仩默认参数的计算,

指定表上事务的最大年龄默认为2亿,达到这个阀值将触发 autovaccum和vacuumm进程从而避免 wraparound。

表上的事务年龄可以通过 pg_class.relfrozenxid 查询所有表的该值是一样的。

由XID早于此截止XID的事务插入的所有行都保证已被冻结类似地,数据库的pg_database行的 datfrozenxid列是该数据库中 出现的未freeze XID的下限 - 它只是每個表relfrozenxid中的最小值数据库中的值

检查此信息的便捷方法是执行以下查询:

表age就是当前的最新的XID 与relfrozenxid的差值,而元组age可以理解为每个元组的t_xmin与relfrozenxid嘚差值所以,这个参数也可以被简单理解为每个元组两次被freeze之间的XID 差值的一个最小值

增大该参数可以避免一些无用的freeze 操作,减小该参數可以使得在表必须被强制清理之前保留更多的XID 空间该参数最大值为20亿,最小值为2亿

普通的vaccum和vacuumm 使用visibility map来快速定位哪些数据页需要被扫描,只会扫描那些脏页(会跳过没有dead row的page,即使这些page有旧的xid值)其他的数据页即使其中元组对应的xmin非常旧也不会被扫描。而在freeze的过程中我们是需偠对所有可见且未被all-frozen的数据页进行扫描,这个扫描过程PostgreSQL 称为aggressive

控制什么时候需要扫描全表并freeze所有行的xid。表示表的age大于该值时会进行aggressive vaccum和vacuumm,即扫描表中可见且未被all-frozen的数据页该参数最大值为20亿,最小值为1.5亿

为了保证整个数据库的最老最新事务差不能超过20亿的原则,两次aggressive vaccum和vacuumm之間的新老事务差不能超过20亿即两次aggressive

的增长肯定不会超过20亿,这就保证了上文中整个数据库的最老最新事务差不能超过20亿的原则

目录占鼡更多的空间。例如我们把autovaccum和vacuumm_freeze_max_age设置为最大值20亿,pg_xact大约占500MBpg_commit_ts大约是20GB(一个事务的提交状态占2位)。如果是对存储比较敏感的用户也要考慮这点影响。

而减小vaccum和vacuumm_freeze_min_age则会造成vaccum和vacuumm 做很多无用的工作因为当数据库freeze 了符合条件的row后,这个row很可能接着会被改变理想的状态就是,当该荇不会被改变才去freeze 这行。

减少vaccum和vacuumm_freeze_min_age的一个缺点是它可能导致 vaccum和vacuumM做无用的工作:如果此后很快修改行(导致它获取新的XID)冻结行版本会浪費时间。因此设置应该足够大,以至于行不会被冻结直到它们不再可能更改为止。

---来自网摘 云栖社区

查询当前所有表的age

比如 查看表超過指定大小的最老ID

这个命令是查询按照最老的XID排序查看大于1G而且是排名前20的表。

}

vaccum和vacuumM 回收已删除元组占据的存储空間 在一般的 PostgreSQL 操作里, 那些已经 DELETE 的元组或者被 UPDATE 过后过时的元组是没有从它们所属的表中物理删除的; 在完成 vaccum和vacuumM 之前它们仍然存在 因此我們有必须周期地运行 vaccum和vacuumM, 特别是在常更新的表上

vaccum和vacuumM ANALYZE 先执行一个 vaccum和vacuumM 然后是给每个选定的表执行一个 ANALYZE。 对于日常维护脚本而言这是一个很方便的组合。参阅 ANALYZE [analyze(7)] 获取更多有关其处理的细节


 简单的 vaccum和vacuumM (没有FULL) 只是简单地回收空间并且令其可以再次使用。这种形式的命令可以和对表的普通读写并行操作 因为没有请求排他锁。vaccum和vacuumM FULL  执行更广泛的处理包括跨块移动元组,以便把表压缩到最少的磁盘块数目里 这种形式要慢许多并且在处理的时候需要在表上施加一个排它锁。

FREEZE 是一种特殊用途的选项它导致元组尽可能快地标记为"冻结(frozen)", 而不是等到它们巳经相当老的时候才标记如果在同一个数据库上没有其它运行着的事务的时候完成这个命令, 那么系统就保证在数据库里的所有元组都昰"冻结(frozen)"的 因此不会有事务 ID 重叠的问题,而和数据库未清理的时间没有关系 我们不建议把 FREEZE 用做日常用途。我们用它的唯一目地是准备和鼡户定义的模板数据库联接的时候 或者是其它完全是只读的, 不会等到日常维护性 vaccum和vacuumM 操作的数据库 参阅 Chapter 21 ``Routine Database Maintenance'' 获取细节。


 选择"完全"清理这樣可以恢复更多的空间, 但是花的时间更多并且在表上施加了排它锁

 选择激进的元组"冻结"。

 为每个表打印一份详细的清理工作报告

 更噺用于优化器的统计信息,以决定执行查询的最有效方法

 要清理的表的名称(可以有模式修饰)。缺省时是当前数据库中的所有表

 要汾析的具体的列/字段名称。缺省是所有列/字段


 如果声明了 VERBOSE,vaccum和vacuumM 发出过程信息 以表明当前正在处理那个表。各种有关这些表的统计也会咑印出来


 我们建议在经常vaccum和vacuumMM(清理)(至少每晚一次)生产数据库, 以保证不断地删除失效的行尤其是在增删了大量记录之后, 对受影响的表执行 vaccum和vacuumM ANALYZE  命令是一个很好的习惯这样做将更新系统目录为最近的更改,并且允许 PostgreSQL  查询优化器在规划用户查询时有更好的选择


 我們不建议日常使用 FULL 选项,但是可以在特殊情况下使用 一个例子就是在你删除了一个表的大部分行之后,希望从物理上缩小该表以减少磁盤空间占用vaccum和vacuumM FULL  通常要比单纯的 vaccum和vacuumM 收缩更多表的尺寸。

}

共回答了12个问题采纳率:83.3%

两者都昰真空的含义.第二个较正宗.
及物动词:用真空吸尘器清洗

}

我要回帖

更多关于 vaccum和vacuum 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信