当前位置: 首页 > article >正文

DeepSeek总结的PostgreSQL MVCC,逐字节解析

来源https://boringsql.com/posts/postgresql-mvcc-byte-by-byte/PostgreSQL MVCC逐字节解析2026-04-17 · Radim Marek你在一个 psql 会话中运行SELECT * FROM orders看到了 5000 万行。你的同事在另一个会话中同时运行相同的查询却看到了 49,999,999 行。你们两个都没有错也没有人看到过时的数据。你们都在读取相同的 8KB 堆页面磁盘上相同的字节。这就是 PostgreSQL 的 MVCC多版本并发控制的承诺也是读者永不阻塞写者、写者永不阻塞读者的原因。它也是存储引擎中最容易被误解的部分之一。人们知道“一行有多个版本”然后就止步于此。答案存在于每个元组的八个字节中。xmin 和 xmax唯一重要的两个 XID如果你读过《深入 8KB 页面》就会知道每个元组都以一个 23 字节的头部开始。该头部的前八个字节是两个 32 位的事务 IDt_xmin插入此版本的事务和t_xmax删除或更新此版本的事务如果仍然存活则为 0。这就是存储层面 MVCC 的核心。PostgreSQL 不维护一个单独的“当前版本”表。它不将任何行标记为“最新”。每个元组都携带自己的两字段时间戳当你的查询读取一个页面时PostgreSQL 必须逐个元组地决定你的事务是否被允许看到它。一个最小的演示CREATETABLEmvcc_demo(idint,valtext);INSERTINTOmvcc_demoVALUES(1,alpha),(2,beta);使用pageinspect窥视原始页面SELECTlp,t_xmin,t_xmax,t_ctidFROMheap_page_items(get_raw_page(mvcc_demo,0));lp|t_xmin|t_xmax|t_ctid----------------------------1|100|0|(0,1)2|100|0|(0,2)(2rows)两个元组。都标记了t_xmin 100执行INSERT的事务和t_xmax 0没有人删除它们。此时数据库上的每个会话都会看到这些行因为每个会话的快照都一致认为事务 100 已提交。现在打开两个并发会话。会话 A 运行一个UPDATE但不提交-- 会话 ABEGIN;UPDATEmvcc_demoSETvalalpha-newWHEREid1;-- 先不要提交再次窥视页面SELECTlp,t_xmin,t_xmax,t_ctidFROMheap_page_items(get_raw_page(mvcc_demo,0));lp|t_xmin|t_xmax|t_ctid----------------------------1|100|101|(0,3)2|100|0|(0,2)3|101|0|(0,3)(3rows)一次UPDATE三个元组。id1的旧版本仍在行指针 1 处标记了t_xmax 101而新版本位于行指针 3 处标记了t_xmin 101。会话 A 尚未提交。事务 101 仍在进行中。会话 B 现在运行SELECT * FROM mvcc_demo仍然看到原始的alpha而不是alpha-new。这三个元组都存在于页面上但会话 B 的快照认为 XID 101 正在进行中因此忽略它所做的一切。可见性决策在每次触碰元组时实时发生。这就是使 MVCC 反直觉的部分磁盘上的字节不会根据谁在询问而改变。改变的是规划器在读取它们时应用的可见性判定。快照pg_current_snapshot()是查看你的会话实际持有的快照的最清晰方式。SELECTpg_current_snapshot();pg_current_snapshot--------------------101:103:101(1row)这是xmin:xmax:xip_list构成了整个快照xmin可能仍在进行中的最小 XID。所有低于此值的 XID 已经确定已提交或已中止。你可以信任它们的t_xmin/t_xmax标记无需进一步检查。xmax第一个尚未分配的 XID。任何大于等于此值的 XID 尚不存在。标记有此 XID 的元组必须被忽略。xip_list介于xmin和xmax之间、且仍在运行的 XID。这些是“进行中”的事务它们的写入对你不可见。PostgreSQL 逐个元组地应用这个测试。如果你的快照认为t_xmin已中止或仍在进行中则该元组对你来说不存在PostgreSQL 会跳过它。如果t_xmin已提交则由t_xmax决定零表示元组存活一个已提交的t_xmax表示有人已删除它你看不到它而一个进行中或已中止的t_xmax表示删除操作尚未进入你的快照。相同的页面。相同的字节。不同的会话有不同的快照因此它们对同一个元组得出不同的结果。交互式 MVCC 可视化工具驱动两个并发会话针对同一个堆页面。观察xmin和xmax标记的变化在READ COMMITTED和REPEATABLE READ之间切换逐个元组追踪可见性规则并在死版本堆积时运行VACUUM。打开可视化工具READ COMMITTED 与 REPEATABLE READPostgreSQL 最常用的两种隔离级别之间的区别归结为一个问题快照是什么时候捕获的READ COMMITTED默认在每个语句开始时捕获一个新的快照。如果另一个会话在你的第一个SELECT和第二个SELECT之间提交了更改你的第二个SELECT会看到更改。世界在你的事务下逐语句地向前发展。REPEATABLE READ在事务开始时捕获一个快照并在后续每个语句中重复使用它。从事务的角度看世界被冻结了。其他会话可以提交一千个更改你的查询始终返回在BEGIN时可见的内容。页面上的字节在两种情况下完全相同。唯一的区别是你的事务携带的是哪个快照。-- 会话 A, READ COMMITTED (默认)BEGIN;SELECTvalFROMmvcc_demoWHEREid1;-- alpha-- 会话 B, 在另一个终端中UPDATEmvcc_demoSETvalalpha-newWHEREid1;-- (自动提交)-- 回到会话 A:SELECTvalFROMmvcc_demoWHEREid1;-- alpha-new 新语句, 新快照COMMIT;现在用REPEATABLE READ重复-- 会话 A, REPEATABLE READBEGINISOLATIONLEVELREPEATABLEREAD;SELECTvalFROMmvcc_demoWHEREid1;-- alpha-new-- 会话 B:UPDATEmvcc_demoSETvalalpha-newerWHEREid1;-- (自动提交)-- 回到会话 A:SELECTvalFROMmvcc_demoWHEREid1;-- 仍然是 alpha-new 与 BEGIN 时相同的快照COMMIT;可视化工具直接展示了这一点每个会话上都有一个隔离级别选择器。在REPEATABLE READ下快照在BEGIN时捕获并持续存在。在READ COMMITTED下每次运行SELECT时都会刷新。观察每个元组上的可见性徽章如何相应变化。每次 UPDATE 都会留下一个死元组PostgreSQL 中的每次UPDATE都会创建一个新的元组版本。旧版本不会消失。它被标记上t_xmax并停留在页面上占用空间直到VACUUM过来回收它。在一个更新频繁的繁忙表上死元组的累积速度可能超过VACUUM清理的速度。这就是“膨胀”也是团队认为 Postgres 需要重新调优的最常见原因之一。MVCC 的契约“永不阻塞始终提供一致视图”是以磁盘空间为代价的。你可以使用pgstattuple看到死元组的累积CREATEEXTENSIONIFNOTEXISTSpgstattuple;-- 大量更新之后SELECTtable_len,tuple_count,dead_tuple_count,dead_tuple_percentFROMpgstattuple(mvcc_demo);table_len|tuple_count|dead_tuple_count|dead_tuple_percent--------------------------------------------------------------8192|2|3|42.15(1row)三个死元组两个活元组42% 的页面空间被浪费。这 42% 的空间将一直浪费直到VACUUM运行或者直到下一次触碰此页面的查询注意到死空间并触发页面级清理。xmin 边界VACUUM只能在没有运行中的事务可能还需要看到它时回收一个死元组。如果会话 B 在五分钟前启动了一个REPEATABLE READ事务并一直空闲它的快照仍然认为id1的更新前版本是存活版本。VACUUM不能触碰它否则会破坏那个会话。因此VACUUM会找到系统上最旧的活动事务并拒绝清理任何比它新的事物。一个长时间运行的REPEATABLE READ事务例如一个需要一小时的分析查询实际上固定住了该小时内产生的每个元组版本。表持续膨胀。Autovacuum 运行发现没有它被允许清理的东西然后退出。长时间运行事务的问题不是 MVCC 的 bug。这正是 MVCC 按设计工作方式。“读者永不阻塞”的代价是读者可能阻塞清理。如果你曾经检查过行为失常的生产数据库上的pg_stat_activity并发现一个空闲了 14 小时的idle in transaction你就会知道这种情况。可视化工具清晰地展示了这一点在会话 B 中启动一个REPEATABLE READ事务让会话 A 运行一堆UPDATE和COMMIT然后点击VACUUM。回收计数不会包括会话 B 仍然可以看到的元组版本。提示位为什么 SELECT 可能弄脏页面新写入后第一个触碰该页面的SELECT可能导致该页面被写回磁盘。不是因为SELECT修改了任何数据而是因为它设置了提示位。当 PostgreSQL 遇到一个t_xmin 101的元组并且需要知道 101 是否已提交时它并非神奇地知道。它必须在pg_xact以前叫pg_clog即提交日志中查找 101。一旦找到答案它会将该答案缓存在元组的t_infomask位中HEAP_XMIN_COMMITTED或HEAP_XMIN_INVALID。未来的读者完全跳过pg_xact查找。设置这些位是一次写入操作。页面因此变脏。它最终会被刷新。你无辜的SELECT最终触发了 I/O。这就是为什么在一个冷表上执行EXPLAIN (ANALYZE, BUFFERS)有时会显示dirtied buffers即使计划中只包含读取操作。这也是为什么“批量加载后的第一个查询”模式会出现神秘的慢速运行的原因你正在为跨越数千个新写入页面设置提示位而支付一次性成本。参阅《理解 EXPLAIN Buffers》了解这些计数器如何显示。一句话总结 MVCC 契约每个元组携带t_xmin和t_xmax。每个事务携带一个快照(xmin, xmax, xip_list)。可见性是一个两阶段查找比较两者。UPDATE和DELETE不原地修改字节。它们在旧版本上标记t_xmax并追加一个新版本。VACUUM清理死版本但仅限于没有活动事务可能还需要它们。长时间运行的事务会阻塞VACUUM。每个SELECT在第一次看到新数据时都可能弄脏页面因为它会将提交状态缓存到提示位中。每个元组八个字节的 XID加上每个事务三个数字的快照再加上一个可见性函数。这就是整个机制但其后果波及 PostgreSQL 操作的每一个部分从膨胀监控到复制再到 autovacuum 调优。关于完整的字节级解析提示位编码、可见性映射、冻结、XID 回卷存储系列文章有详细介绍。如果你从未亲眼见证过 MVCC 的发生可视化工具是建立直观理解的最快方式。让两个会话相互对抗切换隔离级别然后再回到这篇文章。

相关文章:

DeepSeek总结的PostgreSQL MVCC,逐字节解析

来源:https://boringsql.com/posts/postgresql-mvcc-byte-by-byte/ PostgreSQL MVCC,逐字节解析 2026-04-17 Radim Marek 你在一个 psql 会话中运行 SELECT * FROM orders,看到了 5000 万行。你的同事在另一个会话中同时运行相同的查询&a…...

利用python statsmodels包分析数据

原文档地址:https://www.statsmodels.org/stable/index.html 下载statsmodels安装包 aaakylin-pc:~/par$ python3 loong/pip-24.0.pyz download statsmodels -d 313 -i https://mirrors.aliyun.com/pypi/simple/ --platform manylinux2014_aarch64 --only-binary:a…...

R语言预测实战:用predict()函数搞定线性回归与逻辑回归(附完整代码)

R语言预测实战:从模型拟合到商业决策的完整指南 在数据分析的实际应用中,构建模型只是第一步,真正的价值在于如何将模型转化为可操作的商业洞察。R语言中的predict()函数就像数据分析师的瑞士军刀,它能将抽象的统计模型转化为具体…...

从调试到序列化:手把手教你用C++ typeid和type_info实现一个简易类型日志库

从调试到序列化:手把手教你用C typeid和type_info实现一个简易类型日志库 在C开发中,调试和日志记录是每个程序员都绕不开的日常。想象一下这样的场景:你正在维护一个大型代码库,突然收到一个关于类型不匹配的运行时错误报告。如果…...

用Python的statsmodels库做游程检验:从数据清洗到结果解读的完整实战

Python实战:用statsmodels玩转游程检验的7个关键场景 游程检验这个看似冷门的统计方法,在实际业务中能解决哪些棘手问题?当你的A/B测试结果看起来"不太对劲",当用户行为序列出现可疑模式,或者生产线上的质量…...

【STILT模型实操第2期】运行 STILT 模型提供 WRF 示例

目录1. 项目初始化与数据准备1.1 初始化 STILT 项目1.2 下载示例数据1.3 准备转换工具2. 核心操作步骤步骤 1:批量转换 WRF 数据步骤 2:配置 STILT 运行脚本 (r/run_stilt.r)步骤 3:运行 STILT 模型步骤 4:检查输出结果可视化轨迹…...

突破性数据分析利器:Bilivideoinfo让B站视频数据挖掘变得前所未有的简单高效

突破性数据分析利器:Bilivideoinfo让B站视频数据挖掘变得前所未有的简单高效 【免费下载链接】Bilivideoinfo Bilibili视频数据爬虫 精确爬取完整的b站视频数据,包括标题、up主、up主id、精确播放数、历史累计弹幕数、点赞数、投硬币枚数、收藏人数、转发…...

Windows Cleaner终极指南:三步彻底解决C盘爆红问题

Windows Cleaner终极指南:三步彻底解决C盘爆红问题 【免费下载链接】WindowsCleaner Windows Cleaner——专治C盘爆红及各种不服! 项目地址: https://gitcode.com/gh_mirrors/wi/WindowsCleaner Windows Cleaner是一款专为Windows系统设计的开源清…...

从OSM到CARLA:用Python脚本高效构建仿真地图

1. 为什么需要从OSM到CARLA的地图转换 自动驾驶仿真测试离不开高精度的数字地图。CARLA作为开源的自动驾驶仿真平台,使用OpenDRIVE(xodr)格式描述道路网络。但手动绘制xodr地图就像用Excel画CAD图纸——不仅效率低下,还容易出错。…...

英雄联盟助手终极指南:如何一键获取最优出装与符文配置

英雄联盟助手终极指南:如何一键获取最优出装与符文配置 【免费下载链接】champr 🐶 Yet another League of Legends helper 项目地址: https://gitcode.com/gh_mirrors/ch/champr 还在为每次游戏前手动配置出装和符文而烦恼吗?ChampR是…...

8年后端程序员,我为何放弃幻想,转战AI大模型应用开发?(附6条血泪建议)

作者分享自身从8年后端开发转型AI大模型应用开发的经历与感悟。文章指出,AI发展带来职业焦虑,但后端并未“死亡”,而是迎来了全新的AI应用开发领域。转型者无需精通机器学习算法,应掌握Python基础、AI框架应用及实际项目经验。建议…...

从资源死锁到高效协同:深入解析Volcano调度器如何重塑K8s批处理任务调度

1. 当K8s遇上批处理任务:为什么原生调度器会"卡死"? 去年我在给一家AI公司做技术咨询时,遇到一个典型场景:他们的GPU集群总出现"部分Worker启动,整个训练任务卡住"的情况。具体表现是,…...

告别Excel!用Maple Flow搞定电路容差分析,5分钟生成WCCA报告

硬件工程师的效率革命:用Maple Flow实现WCCA分析的智能跃迁 当电路板上的最后一个电阻焊接完毕,硬件工程师的挑战才刚刚开始。最坏情况电路分析(WCCA)就像悬在每位设计者头上的达摩克利斯之剑——传统Excel手工计算不仅耗时数日&a…...

告别下载限速!网盘直链解析工具让你的下载速度飞起来

告别下载限速!网盘直链解析工具让你的下载速度飞起来 【免费下载链接】Online-disk-direct-link-download-assistant 一个基于 JavaScript 的网盘文件下载地址获取工具。基于【网盘直链下载助手】修改 ,支持 百度网盘 / 阿里云盘 / 中国移动云盘 / 天翼云…...

vLLM生产环境部署血泪史:10大坑爹问题及保姆级解决方案,助你少走弯路!

本文分享了vLLM在生产环境部署中的实战经验,涵盖GPU显存碎片、延迟雪崩、长文本输入崩溃等10个常见问题,并提供详细的解决方案和优化配置。通过调整参数、优化模型加载和监控策略,有效提升系统性能和稳定性,帮助开发者顺利实现从D…...

企业网管必看:Win11 22H2默认禁用TLS套件,如何批量修复员工WPA2认证失败?

企业级WiFi认证故障排查:Win11 22H2 TLS策略批量修复指南 当数百台企业终端同时弹出WiFi认证失败提示时,IT支持工单系统往往会在半小时内达到红色警戒线。2023年微软在Windows 11 22H2中默认禁用部分TLS密码套件的安全策略,犹如投入企业网络环…...

别再为上传大文件发愁了!用SpringBoot+阿里云OSS搞定分片、秒传和断点续传,保姆级配置流程

企业级大文件上传实战:SpringBoot与阿里云OSS的高效整合方案 当用户需要上传3GB的设计源文件时,传统表单提交会直接卡死在进度条——这不是假设,而是每天发生在SaaS后台的真实场景。我们曾用一周时间重构某金融科技公司的报表系统&#xff0c…...

从Java转行大模型应用,基于unsloth的量化演示的实战案例内存、推理速度、资源 、性能对比

本文提供可直接复现的 Unsloth 4/8-bit 量化实战案例,覆盖:内存占用优化(显存 / 内存对比)推理速度加速(tokens/s 对比)计算资源消耗降低(GPU 利用率 / 功耗)模型性能无损验证&#…...

Cadence Allegro PCB设计88问解析(二十二) 之 Allegro中封装库的精准调用与版本管理

1. 封装库管理的重要性与常见痛点 在PCB设计流程中,封装库就像建筑师的砖瓦库房。我见过太多项目因为封装管理不善导致的问题:某次设计评审后发现30%的封装版本错误,团队不得不通宵返工;还有更惨痛的案例是批量生产时发现QFN封装焊…...

用STC89C52单片机+收发一体探头,从零DIY一个超声波测距仪(附完整代码和PCB)

从零打造超声波测距仪:STC89C52实战指南 引言 记得第一次接触超声波测距是在大学电子设计竞赛上,看着简单的探头能精确测量距离,那种神奇感至今难忘。如今超声波技术已广泛应用于倒车雷达、工业检测等领域,但自己动手做一个测距仪…...

2026最权威的五大AI科研平台实测分析

Ai论文网站排名(开题报告、文献综述、降aigc率、降重综合对比) TOP1. 千笔AI TOP2. aipasspaper TOP3. 清北论文 TOP4. 豆包 TOP5. kimi TOP6. deepseek 追随人工智能技术的广泛应用,借助AI辅助学术写作变成了高效研究的关键办法。本文…...

2026届毕业生推荐的十大AI论文平台实际效果

Ai论文网站排名(开题报告、文献综述、降aigc率、降重综合对比) TOP1. 千笔AI TOP2. aipasspaper TOP3. 清北论文 TOP4. 豆包 TOP5. kimi TOP6. deepseek 已然成为学术研究新趋向的是借助人工智能展开辅助撰写开题报告,凭借自然语言处理…...

2026届毕业生推荐的六大AI辅助论文方案解析与推荐

Ai论文网站排名(开题报告、文献综述、降aigc率、降重综合对比) TOP1. 千笔AI TOP2. aipasspaper TOP3. 清北论文 TOP4. 豆包 TOP5. kimi TOP6. deepseek 人工智能技术已然极为深入广泛地融入到了高等教育的场景之中,于毕业论文写作的整…...

2025最权威的十大AI论文平台解析与推荐

Ai论文网站排名(开题报告、文献综述、降aigc率、降重综合对比) TOP1. 千笔AI TOP2. aipasspaper TOP3. 清北论文 TOP4. 豆包 TOP5. kimi TOP6. deepseek 对于学术写作而言,论文AI工具已然成了辅助开展研究、优化表达的一种重要资源。这…...

深入PCIe数据包:除了Header和Data,TLP Prefix如何为虚拟化和高性能计算“加戏”?

PCIe TLP Prefix技术解析:从虚拟化到异构计算的底层革新 在数据中心架构持续演进的今天,PCIe总线早已突破传统外设连接的范畴,成为支撑GPU加速、智能网卡、CXL内存池化等前沿技术的核心互连标准。而TLP Prefix作为PCIe协议中一个看似微小的可…...

软件精准营销化的目标客户与触达策略

在数字化浪潮席卷全球的今天,软件精准营销已成为企业提升市场竞争力的核心手段。通过精准识别目标客户并制定高效的触达策略,企业能够以更低的成本实现更高的转化率。本文将深入探讨软件精准营销的目标客户定位与触达策略,帮助企业在激烈的市…...

告别盲调:在KEIL中精准监控与优化栈空间使用

1. 为什么嵌入式开发中栈空间如此重要? 在嵌入式开发中,栈空间的管理往往被很多开发者忽视,直到系统出现莫名其妙的崩溃才追悔莫及。我刚开始做嵌入式开发时,也经常遇到程序运行一段时间后突然死机的情况,调试起来特别…...

从Emoji到图标库:给你的Markdown文档加点‘颜’和‘料’(附Font Awesome/Octicons使用指南)

从Emoji到图标库:给你的Markdown文档加点‘颜’和‘料’(附Font Awesome/Octicons使用指南) 在技术文档的世界里,文字是骨架,而视觉元素则是让文档活起来的血肉。当Unicode Emoji已经无法满足你对文档美学的追求时&…...

Spring Boot REST 异常处理规范

Spring Boot REST 异常处理规范:构建健壮的后端服务 在现代Web开发中,RESTful API已成为前后端交互的核心方式。异常处理不当可能导致接口响应混乱,甚至泄露敏感信息。Spring Boot提供了一套完善的异常处理规范,帮助开发者高效管…...

2026最权威的AI论文网站实际效果

Ai论文网站排名(开题报告、文献综述、降aigc率、降重综合对比) TOP1. 千笔AI TOP2. aipasspaper TOP3. 清北论文 TOP4. 豆包 TOP5. kimi TOP6. deepseek 要切实有效地把文本里 AI 生成的特征予以降低,就得从词汇挑选、句式架构以及逻辑…...