Postgresql为什么需要Freeze?

本文涉及的产品
云原生数据库 PolarDB PostgreSQL 版,标准版 2核4GB 50GB
云原生数据库 PolarDB MySQL 版,通用型 2核4GB 50GB
简介: Freeze PG需要为每个事务分配事务ID,这是MVCC能工作的基础,类似于一个时间戳的概念。 时间戳的做基本动作就是比较大小,即需要得到哪条事务在先,哪条在后。   首先我们来看一下PG中事务ID的比较逻辑,这部分在之前的某一起DB月报中也介绍过。 /* * TransactionIdPrecedes --- is id1 logically < id2? */boo

Freeze

PG需要为每个事务分配事务ID,这是MVCC能工作的基础,类似于一个时间戳的概念。

时间戳的做基本动作就是比较大小,即需要得到哪条事务在先,哪条在后。

 

首先我们来看一下PG中事务ID的比较逻辑,这部分在之前的某一起DB月报中也介绍过。

/*
* TransactionIdPrecedes --- is id1 logically < id2?
*/
bool
TransactionIdPrecedes(TransactionId id1, TransactionId id2)
{
/*
* If either ID is a permanent XID then we can just do unsigned
* comparison. If both are normal, do a modulo-2^32 comparison.
*/
int32 diff;

if (!TransactionIdIsNormal(id1) || !TransactionIdIsNormal(id2))
return (id1 < id2);

diff = (int32) (id1 - id2);
return (diff < 0);
}

TransactionIdIsNormal宏的作用是判断id1是否大于等于3。这里值得注意的是diff = (int32) (id1 - id2)。这里使用了一个编程技巧,比如发生了事务ID回卷:

id1 = 4294967200
id2 = 100

// int32   -2147483648 ~ 2147483647 (32亿+)
// uint32   0 ~ 4294967295 (42亿+)

id1 - id2 = 4294967100这个值强转成(int32)类型后是一个负数,会发生return true,函数会认为id1 < id2,也就是说id2是更新的事务。

我们继续考虑下一个场景,id2继续增长到21亿多时,id1和id2的差值已经在int32的范围内了,所以diff会大于零,return false函数会认为id1= 42亿+ > id2= 21亿+,结论是id1是更新的事务!这里就出现问题了,一个老事务被判断成了新事务。

所以PostgreSQL必须保证一个数据库中两个有效的事务之间的年龄差最多是,约为20亿。

1 Lazy Freeze

关注参数:

vacuum_freeze_min_age = 50000000(5千万)

lazy freeze是autovacuum和vacuum都会做的动作,所以vm在这里也是有效的,只有vm中标记的页面会做lazy freeze。

触发条件:

xmin小与freeze_txid的元组都会被freeze。

freeze_txid = current_oldest_xmin - vacuum_freeze_min_age
          = 当前活跃的最小的xid - 参数vacuum_freeze_min_age

例如当前活跃的最小xid=50005100,vacuum_freeze_min_age为默认值50000000,那么freeze_txid=5100,也就是说xmin小于5100的元组都会被freeze(前提是所在的页面会被扫描到) 

这里补充一个长事务的例子:

数据库运行一个长事务,很久没有提交导致current_oldest_xmin一直不会超过vacuum_freeze_min_age,vacuum不会冻结任何元组。这样最低的xmin就和当前最新的xmin的距离越来越远,差值慢慢接近20亿,这时候数据库为保证数据不丢失,会有告警甚至宕机。

告警

 WARNING:  database "mydb" must be vacuumed within 177009986 transactions
HINT: To avoid a database shutdown, execute a database-wide VACUUM in "mydb".

宕机

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.

2 Eager Freeze

关注参数:

vacuum_freeze_table_age = 150000000(1亿5千万)

触发条件:

pg_database.datfrozenxid < (OldestXmin−vacuum_freeze_table_age)

pg_database.datfrozenxid : 当前数据库被冻结的最大的事务ID,pg_database中可以查到

例如我们查询到当前的pg_database.datfrozenxid和vacuum_freeze_table_age的值为

select oid,datname,datfrozenxid from pg_database where oid=13214;
oid | datname | datfrozenxid
-------+----------+--------------
13214 | postgres |          548

show vacuum_freeze_table_age;
vacuum_freeze_table_age
-------------------------
150000000

这种情况下当OldestXmin > 150000000 = 548也就是当前最小的活跃事务大于1亿4千万+的时候才会触发eager freeze。

所以触发eager freeze的条件可以这样理解,当前最小的活跃事务ID 与 数据库最大的FREEZE事务ID的差值超过了1亿5千万(vacuum_freeze_table_age),就会触发eager freeze。

相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
目录
相关文章
|
关系型数据库 数据库 PostgreSQL
PostgreSQL技术周刊第26期:vacuum freeze无法回收事务号问题分析
PostgreSQL(简称PG)的开发者们:云栖社区已有5000位PG开发者,发布了3000+PG文章(文章列表),沉淀了700+的PG精品问答(问答列表)。 PostgreSQL技术周刊会为大家介绍最新的PG技术与动态、预告活动、最热问答、直播教程等,欢迎大家订阅PostgreSQL技术周刊。
3730 0
|
关系型数据库 PostgreSQL
PostgreSQL的"天气预报" - 如何预测Freeze IO风暴
还记得我写的这篇文档吗? 《PostgreSQL 大表自动 freeze 优化思路》https://yq.aliyun.com/articles/50411 文章主要针对如何优化大表的freeze调度来解决IO风暴的问题。 预测 IO 风暴 那么在没有针对性的调度策略之前,我们如何预测
3574 0
|
关系型数据库 PostgreSQL
PostgreSQL 大表自动 freeze 优化思路
PostgreSQL 的版本冻结是一个比较蛋疼的事情,为什么要做版本冻结呢?因为PG的版本号是uint32的,是重复使用的,所以每隔大约20亿个事务后,必须要冻结,否则记录会变成未来的,对当前事务"不可见"。冻结的事务号是2 src/include/access/transam.h #def
5408 0
|
9天前
|
存储 SQL 关系型数据库
Mysql学习笔记(二):数据库命令行代码总结
这篇文章是关于MySQL数据库命令行操作的总结,包括登录、退出、查看时间与版本、数据库和数据表的基本操作(如创建、删除、查看)、数据的增删改查等。它还涉及了如何通过SQL语句进行条件查询、模糊查询、范围查询和限制查询,以及如何进行表结构的修改。这些内容对于初学者来说非常实用,是学习MySQL数据库管理的基础。
43 6
|
7天前
|
存储 关系型数据库 MySQL
Mysql(4)—数据库索引
数据库索引是用于提高数据检索效率的数据结构,类似于书籍中的索引。它允许用户快速找到数据,而无需扫描整个表。MySQL中的索引可以显著提升查询速度,使数据库操作更加高效。索引的发展经历了从无索引、简单索引到B-树、哈希索引、位图索引、全文索引等多个阶段。
38 3
Mysql(4)—数据库索引
|
9天前
|
SQL Ubuntu 关系型数据库
Mysql学习笔记(一):数据库详细介绍以及Navicat简单使用
本文为MySQL学习笔记,介绍了数据库的基本概念,包括行、列、主键等,并解释了C/S和B/S架构以及SQL语言的分类。接着,指导如何在Windows和Ubuntu系统上安装MySQL,并提供了启动、停止和重启服务的命令。文章还涵盖了Navicat的使用,包括安装、登录和新建表格等步骤。最后,介绍了MySQL中的数据类型和字段约束,如主键、外键、非空和唯一等。
27 3
Mysql学习笔记(一):数据库详细介绍以及Navicat简单使用
|
14天前
|
缓存 算法 关系型数据库
Mysql(3)—数据库相关概念及工作原理
数据库是一个以某种有组织的方式存储的数据集合。它通常包括一个或多个不同的主题领域或用途的数据表。
38 5
Mysql(3)—数据库相关概念及工作原理
|
1天前
|
存储 关系型数据库 MySQL
如何在MySQL中创建数据库?
【10月更文挑战第16天】如何在MySQL中创建数据库?