PostgreSQL中的冻结管理

网友投稿 1010 2022-10-26

本站部分文章、图片属于网络上可搜索到的公开信息,均用于学习和交流用途,不能代表睿象云的观点、立场或意见。我们接受网民的监督,如发现任何违法内容或侵犯了您的权益,请第一时间联系小编邮箱jiasou666@gmail.com 处理。

PostgreSQL中的冻结管理

■ 译者简介张岩&崔鹏&海能达DBA团队,任职于海能达通信股份有限公司哈尔滨平台中心,数据库开发高级工程师,致力于PostgreSQL数据库在专网通信领域、公共安全领域的应用与推广,个人兴趣主要集中在:分布式数据库系统设计、高并发高可用数据库架构设计与开源数据库的源码研究。■ 校对者简介朱君鹏,博士研究生。主要研究方向为数据库管理系统,尤其是内存数据库、事务处理系统、软硬件协同设计、日志系统。个人github https://github.com/EthanZhu-DBPostgreSQL包含一个变化的事件范围,它实际上在当前事务id之前或之后大约20亿个事务。当前事务id前面超过20亿或后面超过20亿的事务被认为是未来的事务,因此对当前事务是不可见的。

PostgreSQL通过特殊地标记旧行来避免这种灾难性的数据丢失,这样无论它们与当前事务id处于什么位置,它们都是可见的。

Freezing冻结是对旧的活元组(即数据库行)进行标记的过程,这样它们就不会被变化的事件范围覆盖,否则它们就会在未来出现。这与vacuum相反,vacuum指的是释放那些已死的元组所占用的空间,这些元组对任何事务都不再可见。

这两个过程都由vacuum管理。

有许多设置可以控制如何冻结。

首先,vacuum_freeze_min_age控制在vacuum已经查看页面以确定是否有可以清理的死元组时,元组是否会被冻结。在这种情况下,比vacuum_freeze_min_age更早的元组将被冻结。将这个值设置得较低意味着以后要做的工作将更少,但可能CPU和IO或WAL要付出额外代价。通常,您可能希望这个设置至少能处理几个小时的事务。假设您希望以持续的速度每秒处理最多2000个事务。2000 TPS是每小时720万笔交易。因此,在这种情况下一个更激进的设置方式是20m。默认设置为50m。和vacuum_multixact_freeze_min_age参数相似。注意,transaction_id和multixid计数器是独立的-您需要同时跟踪它们。

其次是vacuum_freeze_table_age和vacuum_multixact_freeze_table_age参数。这些设置决定了autovacuum何时不仅查看可能有死行的页面,还查看可能有未冻结行的页面。这些设置的默认值是150m。如果您将vacuum_freeze_min_age减少得足够多,那么在很多情况下,这种更激进的vacuum将很少或根本不需要做任何工作。无论如何,这个过程不像以前那么繁忙了,因为现代版本的PostgreSQL(9.6及以上)保留了一个所有元组都被冻结的页面映射,并且只访问那些没有全部冻结的页面。这意味着它不再是一个全表扫描。

最后是autovacuum_max_freeze_age参数。如果最后一次完全扫描表以查找未冻结的行的次数超过了以前的许多事务,那么autovacuum将在表上启动一个 anti-wraparound vacuum。默认值是200m。类似地,autovacuum_multixact_freeze_max_age的默认值是400m。这是你真正想要避免的。有两件事可以做。首先,将这些设置增加到10亿左右是很常见的,以给你自己更多的空间,尤其是在交易量大的系统上。您可以做得更多,但是您希望在最老的元组和事件范围之间有足够的事务空间。其次,在任何数据库遇到这种情况之前,监视您的系统并采取补救措施是很重要的。这种补救措施通常包括手动vacuum。

一个可能发生的问题是,你的DDL导致正常(即不是anti-wraparound)自动vacuum取消自己。如果这样做的时间足够长,最终将强制执行一个anti-wraparound vacuum,然后任何DDL都会在vacuum过程之后排队,这反过来又会阻塞任何进一步的DML。在这个阶段,你的表实际上是不可读的,直到vacuum完成。这取决于数据库的使用模式,但这不仅仅是理论上的可能性,PostgreSQL部署和dba确实需要考虑到这一点。

监控数据库集群对于管理这一点至关重要。特别是,您需要监视集群中每个数据库的datfrozenxid和datminmxid,如果它们太旧,在需要 anti-wraparound vacuum之前采取补救措施。通常问题出在数据库中的一个或几个表上。通过检查数据库中表的relfrozenxid和relminmxid来发现问题所在。age()和mxid_age()函数分别用于发现事务id和multixid计数器的年龄。

冻结不是您可以避免的事情,它是Postgres中一项重要的维护活动,需要积极管理。

上一篇:Redis学习笔记-并发控制&分布式锁
下一篇:终端自动化测试探索之路
相关文章

 发表评论

暂时没有评论,来抢沙发吧~