事务ID(XID)基本概念

从Transactions and Identifiers可知:

事务 ID,例如 278394,会根据 PostgreSQL 集群内所有数据库使用的全局计数器按顺序分配给事务。此分配会在事务首次写入数据库时进行。这意味着编号较低的 xid 会先于编号较高的 xid 写入。
 
事务 ID 类型 xid 为 32 位宽,每 40 亿次事务绕回一次。每次绕回时,都会增加一个 32 位的纪元 (epoch)。此外,还有一个 64 位类型 xid8,它包含这个纪元,因此在安装的生命周期内不会绕回;它可以通过强制类型转换转换为 xid。xid 是 PostgreSQL MVCC 并发机制和流复制的基础

交易ID和快照信息函数参见这里。

日常清理(VACUUM)中的冻结操作

PostgreSQL 数据库需要定期维护,称为清理(vacuum)。其中除更新统计信息,回收空间外,一项重要的任务就是防止由于事务 ID 回绕或多事务 ID 回绕而丢失非常旧的数据。

从Preventing Transaction ID Wraparound Failures可知:

PostgreSQL 的 MVCC 事务语义依赖于能够比较事务 ID (XID) 编号:如果行版本的插入 XID 大于当前事务的 XID,则该行版本“位于未来”,对当前事务不可见。但由于事务 ID 的大小有限(32 位),因此长期运行的集群(超过 40 亿个事务)将遭遇事务 ID 回绕:XID 计数器会回绕为零,过去的事务会突然变成未来的事务 — — 这意味着它们的输出变得不可见。简而言之,就是灾难性的数据丢失。(实际上数据仍然存在,但如果您无法获取数据,这也只是些安慰。)为了避免这种情况,有必要至少每 20 亿个事务清理一次每个数据库中的每个表。

为何是至少每 20 亿个事务清理一次,这是由autovacuum_freeze_max_age参数控制的:

sampledb=> show autovacuum_freeze_max_age;autovacuum_freeze_max_age
---------------------------200000000
(1 row)

20 亿实际是XID取值范围的一半,即231

定期清理能够解决这个问题的原因是,VACUUM 会将行标记为冻结,表明这些行是由一个提交时间足够久的事务插入的,因此插入事务的影响对所有当前和未来的事务都可见。普通 XID 使用模 232 算法进行比较。这意味着对于每个普通 XID,都有 20 亿个“更旧”的 XID 和 20 亿个“更新”的 XID;换句话说,普通 XID 空间是循环的,没有端点。因此,一旦使用特定的普通 XID 创建了行版本,那么在接下来的 20 亿个事务中,无论我们讨论的是哪个普通 XID,该行版本都会看起来像是“过去”的。如果在超过 20 亿个事务之后,该行版本仍然存在,它就会突然看起来像是未来。为了防止这种情况,PostgreSQL 保留了一个特殊的 XID,FrozenTransactionId,它不遵循普通 XID 比较规则,并且始终被认为比所有普通 XID 都旧。冻结行版本被视为插入 XID 是 FrozenTransactionId,因此无论环绕问题如何,它们对于所有正常事务都将显示为“过去”,因此此类行版本将一直有效,直到被删除,无论时间有多长。

所谓是循环的,没有端点类似于下图:

012...2^32-101...

每一个表都有系统定义的隐含列,xmin和xmax:

sampledb=> select xmin, xmax from regions limit 1;xmin | xmax
------+------5190 |    0
(1 row)

所谓冻结就是将xmin的值设为FrozenTransactionId(实际值为2),设置后xmin的值不会再被修改。

vacuum_freeze_min_age 控制 XID 值的有效期,超过该 XID 值的行才会被冻结。如果原本会被冻结的行很快会被再次修改,则增加此设置可以避免不必要的工作;但降低此设置会增加在必须再次清理表之前可以处理的事务数。

表未清理的最长时间是20亿个事务数减去上次激进清理时的vacuum_freeze_min_age值。如果未清理的时间超过该时间,可能会导致数据丢失。为确保不会发生这种情况,任何可能包含XID大于配置参数autovacuum_freeze_max_age指定的未冻结行的表都会被调用自动清理。(即使禁用自动清理,也会发生这种情况。)

事务ID环绕问题是如何产生和解决的

前面已经谈到了普通 XID 使用模 232 算法进行比较。这个规则就是:

如果(NextXID - xmin) % 2^32 < 2^31,则 xmin 属于过去

PostgreSQL 将 “当前 XID ± 2^31 (≈ 20 亿)” 作为 可见窗口,因此总有约20亿属于过去,20亿属于未来(中间那个|即NextXID):

<---------------- 2^31 = 2,147,483,648 ---------------->“过去”                   “未来”
-----------------------|------------------------------>可见                   不可见

先看一个属于过去的例子。

假设xmin = 4,294,967,000,接近2^32。XID已经回绕,此时NextXID = 100。
根据算法(NextXID - xmin) % 2^32 < 2^31

NextXID = 100
xmin = 4,294,967,000
delta = (100 - 4,294,967,000) % 4,294,967,296= ( -4,294,966,900 ) % 4,294,967,296= 396

显然,396小于2^31,因此xmin虽然接近XID的最大值,但属于过去。

再看一个属于未来的例子,xmin和上例相同:

NextXID = 2,147,483,700
xmin = 4,294,967,000
delta = (2,147,483,700 - 4,294,967,000) % 4,294,967,296= (-2,147,483,300) % 4,294,967,296= 2,147,483,996

此时,delta大于2^31,因此xmin属于未来。

xmin并没有发生变化,而此时却被视为未来,这显然是错误的。通过冻结,即将xmin置为FrozenTransactionId,即可解决事务ID环绕问题。

在源码文件./backend/access/transam/transam.c中,可以找到此算法:

// git clone https://github.com/postgres/postgres.git 检出源码
/** 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);
}

监控XID环绕

postgres=# SELECT datname,age(datfrozenxid) AS xid_age,2000000000 - age(datfrozenxid) AS remaining_before_wraparound
FROM pg_database;datname       | xid_age | remaining_before_wraparound
--------------------+---------+-----------------------------postgres           |    5375 |                  1999994625template1          |    5375 |                  1999994625template0          |    5375 |                  1999994625world_temperatures |    5375 |                  1999994625demo               |    5375 |                  1999994625sampledb           |    5375 |                  1999994625
(6 rows)

可以参照Transaction ID wraparound: a walk on the wild side,模拟事务ID环绕问题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/915815.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/915815.shtml
英文地址,请注明出处:http://en.pswp.cn/news/915815.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

高等数学-矩阵知识

好的&#xff0c;我们来详细讲解高等数学&#xff08;主要是线性代数部分&#xff09;中的核心矩阵知识。矩阵是线性代数的基石&#xff0c;广泛应用于数学、物理、工程、计算机科学、经济学等众多领域。 一、矩阵的基本概念定义&#xff1a; 一个 m n 矩阵 (Matrix) 是一个由…

React 项目性能优化概要

应用级性能优化&#xff0c;需要结合实际需求展开分析&#xff0c;通常我们需要从以下几个方面来考虑&#xff1a; 1. 识别性能瓶颈 识别性能瓶颈是优化的第一步&#xff0c;通过各种工具和方法找到影响性能的主要原因&#xff1a; React Profiler&#xff1a;使用 React Dev…

【web自动化】-5- fixture集中管理和项目重构

一、投标用例设计 # 定义让前台页面保持自动登录的fixture pytest.fixture() def user_driver():driver webdriver.Chrome()driver.get("http://47.107.116.139/fangwei/")driver.maximize_window()# 创建页面类对象page ReceptionLoginPage(driver)# 通过页面类对…

Dify工作流:爬虫文章到AI知识库

部署Dify 代码拉取 git clone https://github.com/langgenius/dify.git cd dify/docker启动容器 docker-compose up -d启动成功准备知识库 创建知识库 创建一个空的知识库要先从网址中&#xff0c;找到这个知识库的id&#xff0c;记下后面需要用到。新建API密钥 创建密钥&#…

支付鉴权方案介绍

前后端交互中的鉴权是确保请求来源合法、身份可信、权限合适的关键手段。不同系统架构和业务类型下,使用的鉴权方式略有不同,但主要可分为以下几类: ✅ 一、前后端交互常见的鉴权方式概览 鉴权方式 优点 缺点 适用场景 Cookie + Session 简单、成熟,服务端易控制 不适合跨域…

halcon处理灰度能量图

使用halcon处理射线图像&#xff0c;对高能区域和低能区域分割处理感兴趣区域&#xff0c;筛选区域下的灰度值区间范围。图像灰度值为16位深度图。* 读取灰度图像 read_image (Image, /123.tif)** 获取图像尺寸 get_image_size (Image, Width, Height)* 分割图像为左右两部分&a…

Oracle From查看弹性域设置

打开弹性与设置&#xff1a;【应用开发员->弹性域->说明性->段】打开后界面如下&#xff1a; 把光标定位到标题&#xff0c;然后点击“手电筒”搜索名称&#xff08;名称就是你要查询的那个弹性域的名称&#xff09;我这里就是搜索“附加题头信息”&#xff0…

git初始流程

对于一个新项目&#xff0c;从 Git 仓库拉取 test_tool 分支并进行后续修改提交的完整流程如下&#xff1a; 一、首次拉取项目&#xff08;克隆仓库并切换分支&#xff09;克隆远程仓库到本地 打开终端&#xff08;或 PyCharm 的 Terminal&#xff09;&#xff0c;进入你想存放…

emuelec模拟器 ,s905盒子树莓派街机游戏

EmuELEC支持的盒子类型相当广泛&#xff0c;主要包括使用以下芯片方案的机顶盒等设备&#xff1a; S905系列及其变体&#xff1a;如S905、S905D、S905L、S905M、S905X、S905X2、S905X3、S905X4、S905W、S905Y等。 S912&#xff1a;这也是EmuELEC支持的一个常见芯片方案。 S922x…

Ansible部署

Ansible部署 一、部署环境及前置操作 1、测试环境 注:主机复用原测试环境&#xff0c;主机hostname根据需求调整 硬件环境&#xff1a;N100 x86主机 Proxmox系统 软件环境&#xff1a;Ubuntu 22.04.3 LTS 软件版本&#xff1a;redis-7.4.0.tar.gz 主机环境&#xff1a;主机IP …

智慧教室:科技赋能,奏响个性化学习新乐章

在传统教育模式中&#xff0c;课堂互动的局限性犹如一道无形的枷锁&#xff0c;束缚着学生主动学习的热情与能力。课堂上&#xff0c;往往是教师单向的知识输出&#xff0c;仅有少数学生能获得发言机会&#xff0c;大部分学生只能被动聆听&#xff0c;逐渐在枯燥的学习氛围中丧…

Android埋点实现方案深度分析

埋码是数据驱动业务决策、产品优化、用户行为分析的核心基础&#xff0c;其实现方案的优劣直接影响数据的准确性、完整性、实时性、可维护性以及开发效率。 以下从多个维度对主流方案进行剖析&#xff1a; 一、核心目标与挑战目标&#xff1a; 精准采集&#xff1a; 在用户触发…

万界星空科技铜线/漆包线行业智能化MES系统解决方案

万界星空科技针对铜线及漆包线行业开发的智能化MES系统&#xff0c;专门解决该行业原材料管理复杂、工艺控制严、质量追溯困难等核心痛点。该系统通过数字化手段实现生产全流程的可视化与精准控制&#xff0c;助力企业提升生产效率、降低运营成本并增强市场竞争力。一、行业专属…

Git 完全手册:从入门到团队协作实战(3)

Hello大家好&#xff01;很高兴我们又见面啦&#xff01;给生活添点passion&#xff0c;开始今天的编程之路&#xff01; 我的博客&#xff1a;<但凡. 我的专栏&#xff1a;《编程之路》、《数据结构与算法之美》、《C修炼之路》、《Linux修炼&#xff1a;终端之内 洞悉真理…

使用Docker搭建SearXNG搜索引擎

1、安装Docker# 安装Docker https://docs.docker.com/get-docker/# 安装Docker Compose https://docs.docker.com/compose/install/# CentOS安装Docker https://mp.weixin.qq.com/s/nHNPbCmdQs3E5x1QBP-ueA2、安装SearXNG详见&#xff1a; https://docs.searxng.org/admin/inst…

基于pi/4-QPSK扩频解扩和gardner环定时同步的通信系统matlab性能仿真

目录 1.引言 2.算法仿真效果演示 3.数据集格式或算法参数简介 4.算法涉及理论知识概要 4.1 π/4-QPSK 4.2 直接序列扩频与解扩 4.3 Gardner环定时同步 5.参考文献 6.完整算法代码文件获得 1.引言 π/4-QPSK是一种特殊的QPSK调制方式&#xff0c;其相邻符号间的相位跳变…

CGA老年人能力评估师:提升老年生活质量

一、CGA老年人能力评估师是提升老年生活质量的“导航者” 老年生活质量的提升&#xff0c;始于对老年人真实需求的精准把握。CGA老年人能力评估师正是这样一群“导航者”&#xff0c;他们运用CGA老年综合评估系统&#xff0c;深入了解老年人在生理、心理、社会参与等方面的状况…

开源的大语言模型(LLM)应用开发平台Dify

概述Dify 是一个开源的大语言模型&#xff08;LLM&#xff09;应用开发平台&#xff0c;结合了后端即服务&#xff08;Backend-as-a-Service&#xff09;和 LLMOps 的理念&#xff0c;旨在帮助开发者快速构建生产级的生成式 AI 应用。它通过直观的界面、强大的功能和灵活的部署…

RAG(检索增强生成)里的文档管理

RAG&#xff08;检索增强生成&#xff09;是结合检索与生成式 AI 的技术框架。核心逻辑是先从外部知识库精准检索相关信息&#xff0c;再将其作为上下文输入大模型生成回答。技术上依赖检索引擎&#xff08;如向量数据库、BM25&#xff09;、大语言模型&#xff08;如 GPT、LLa…

床上肢体康复机器人的机械结构设计cad【7张】三维图+设计说明书

摘要 近年来&#xff0c;随着人口老龄化问题的加重&#xff0c;常年卧床的老年人数增多&#xff0c;同时因为各种疾病的原因&#xff0c;患肢体功能障碍的人数也在增加。严重影响着患者的生活质量&#xff0c;同时给社会和家庭增加了很多麻烦。他们迫切希望尽快康复&#xff0c…