Postgresql源码(157)Redo系列MultiXact Redo (RM_MULTIXACT_ID = 6)
相关《Postgresql源码156MultiXact机制分析》总结一个行锁xmax直接放xid。两个行锁xmax放multixactid然后multixactid1 → offsetoffset → 数据。双SLRU存储请参考[《Postgresql源码156MultiXact机制分析》]。(https://blog.csdn.net/jackgo73/article/details/158853458)再来一个行锁的话不会修改现有multixact记录会新增一条multixactid2先把1的数据考过来然后在追加新的。行锁等的是什么锁是从xmax位置读出来的xid然后给事务id加锁所以等的是事务id锁XactLockTableWait。四种multixact日志WAL 类型宏值redo 核心动作触发场景ZERO_OFF_PAGEXLOG_MULTIXACT_ZERO_OFF_PAGE0x00ZeroMultiXactOffsetPage()MXact ID 跨入新 offsets 页面ZERO_MEM_PAGEXLOG_MULTIXACT_ZERO_MEM_PAGE0x10ZeroMultiXactMemberPage()member 偏移量跨入新 members 页面CREATE_IDXLOG_MULTIXACT_CREATE_ID0x20RecordNewMultiXact() 推进计数器两个以上事务对同一行持锁TRUNCATE_IDXLOG_MULTIXACT_TRUNCATE_ID0x30PerformMembersTruncation()PerformOffsetsTruncation()VACUUM 清理过时的 MultiXactmultixact_redo 调试调试SQL-- Session 1:BEGIN;SELECT*FROMtest_multiWHEREid1FORSHARE;-- 此时 xmax 还是普通 xid-- Session 2:BEGIN;SELECT*FROMtest_multiWHEREid1FORSHARE;-- 此时 PostgreSQL 需要创建一个 MultiXact 来容纳两个事务的锁-- 触发 MultiXactIdCreate() - 写入 XLOG_MULTIXACT_CREATE_ID-- 物理日志会立即发到备库在备库上会触发multixact_redo备库再来一个新会话对这一行加share锁这里并没有修改mid7的记录而是直接新增mid8现在有三个事务对这一行加了share锁这时来一个update锁事务ID开始等锁这时不会产生WAL这时再来再来一个事务加share锁会继续加进去没有等锁队列。multixact_redo代码分析voidmultixact_redo(XLogReaderState*record){uint8 infoXLogRecGetInfo(record)~XLR_INFO_MASK;/* MultiXact 记录不使用 backup block */Assert(!XLogRecHasAnyBlockRefs(record));if(infoXLOG_MULTIXACT_ZERO_OFF_PAGE){/* * 处理 ZERO_OFF_PAGE: 零化 offsets SLRU 新页面 * offsets SLRU 存储 MultiXactId - member偏移量 的映射 */intpageno;intslotno;memcpy(pageno,XLogRecGetData(record),sizeof(int));/* 加锁后零化 offsets SLRU 页面, 然后立即写盘 */LWLockAcquire(MultiXactOffsetSLRULock,LW_EXCLUSIVE);slotnoZeroMultiXactOffsetPage(pageno,false);SimpleLruWritePage(MultiXactOffsetCtl,slotno);Assert(!MultiXactOffsetCtl-shared-page_dirty[slotno]);LWLockRelease(MultiXactOffsetSLRULock);}elseif(infoXLOG_MULTIXACT_ZERO_MEM_PAGE){/* * 处理 ZERO_MEM_PAGE: 零化 members SLRU 新页面 * members SLRU 存储实际的 (xid, lock_mode) 成员列表 */intpageno;intslotno;memcpy(pageno,XLogRecGetData(record),sizeof(int));LWLockAcquire(MultiXactMemberSLRULock,LW_EXCLUSIVE);slotnoZeroMultiXactMemberPage(pageno,false);SimpleLruWritePage(MultiXactMemberCtl,slotno);Assert(!MultiXactMemberCtl-shared-page_dirty[slotno]);LWLockRelease(MultiXactMemberSLRULock);}elseif(infoXLOG_MULTIXACT_CREATE_ID){/* * 处理 CREATE_ID: 重建 MultiXact 记录 * 将 MultiXact 的 offset 和 members 写回 SLRU 文件 */xl_multixact_create*xlrec(xl_multixact_create*)XLogRecGetData(record);TransactionId max_xid;inti;/* * 核心动作: 将数据写回 SLRU 文件 * RecordNewMultiXact 会: * 1. 在 offsets SLRU 中记录 mid - moff 的映射 * 2. 在 members SLRU 中写入 nmembers 个 MultiXactMember */RecordNewMultiXact(xlrec-mid,xlrec-moff,xlrec-nmembers,xlrec-members);/* * 推进 nextMXact 和 nextOffset 计数器 * 确保它们不小于本记录中的值, 避免重复分配 */MultiXactAdvanceNextMXact(xlrec-mid1,xlrec-moffxlrec-nmembers);/* * 确保 nextXid 不小于记录中提到的任何 XID * 这应该是多余的(这些 XID 在其他 WAL 中也有记录), * 但作为安全措施仍然执行 */max_xidXLogRecGetXid(record);for(i0;ixlrec-nmembers;i){if(TransactionIdPrecedes(max_xid,xlrec-members[i].xid))max_xidxlrec-members[i].xid;}AdvanceNextFullTransactionIdPastXid(max_xid);}elseif(infoXLOG_MULTIXACT_TRUNCATE_ID){/* * 处理 TRUNCATE_ID: 截断旧 MultiXact 数据 */xl_multixact_truncate xlrec;intpageno;memcpy(xlrec,XLogRecGetData(record),SizeOfMultiXactTruncate);elog(DEBUG1,replaying multixact truncation: offsets [%u, %u), offsets segments [%x, %x), members [%u, %u), members segments [%x, %x),xlrec.startTruncOff,xlrec.endTruncOff,MultiXactIdToOffsetSegment(xlrec.startTruncOff),MultiXactIdToOffsetSegment(xlrec.endTruncOff),xlrec.startTruncMemb,xlrec.endTruncMemb,MXOffsetToMemberSegment(xlrec.startTruncMemb),MXOffsetToMemberSegment(xlrec.endTruncMemb));/* 获取截断锁, 防止并发操作 */LWLockAcquire(MultiXactTruncationLock,LW_EXCLUSIVE);/* * 推进 horizon 值(最老 MultiXact 限制), 确保恢复结束时是最新的 */SetMultiXactIdLimit(xlrec.endTruncOff,xlrec.oldestMultiDB,false);/* 截断 members SLRU 段文件 */PerformMembersTruncation(xlrec.startTruncMemb,xlrec.endTruncMemb);/* * 截断 offsets SLRU 段文件 * 在回放期间 latest_page_number 可能尚未设置, * 需要手动插入一个合适的值来绕过 SimpleLruTruncate 的健全性检查 */pagenoMultiXactIdToOffsetPage(xlrec.endTruncOff);MultiXactOffsetCtl-shared-latest_page_numberpageno;PerformOffsetsTruncation(xlrec.startTruncOff,xlrec.endTruncOff);LWLockRelease(MultiXactTruncationLock);}elseelog(PANIC,multixact_redo: unknown op code %u,info);}

相关新闻

c++ static关键字的详细用法和作用

c++ static关键字的详细用法和作用

一.前言在讲static之前,先明确两个关键术语: 生命周期:变量从创建到销毁的时间段(全局变量生命周期是整个程序运行期,局部变量是所在函数执行期); 作用域:变量 / 函数能被访问的范…

2026/5/17 5:23:13 阅读更多 →
散热器产业的下一步:从“金属件”到“系统级热管理模块”的结构升级

散热器产业的下一步:从“金属件”到“系统级热管理模块”的结构升级

观点 如果只把散热器理解为一个“金属散热件”,就很难看懂这个行业的下一步。真正发生变化的并不是散热器本身,而是电子系统的功率密度曲线正在陡峭上升: AI服务器、功率半导体、电动汽车电驱系统、5G通信设备——这些系统正在把热管理从“配…

2026/5/17 11:56:59 阅读更多 →
PPT Timer:一个置顶于PPT全屏放映之上的LCD倒计时器

PPT Timer:一个置顶于PPT全屏放映之上的LCD倒计时器

演讲超时?课堂拖堂?用一个赛博朋克风格的桌面倒计时器,帮你精准掌控每一分钟。 痛点 讲PPT的时候,你大概率遇到过这些场景: 答辩给了8分钟,讲到一半才发现已经过了6分钟手机计时器被PPT全屏挡住&#xff…

2026/5/17 11:56:58 阅读更多 →

最新新闻

爬虫入门:requests+BeautifulSoup抓取网页

爬虫入门:requests+BeautifulSoup抓取网页

一、引言:为什么学习爬虫 在大数据时代,数据是驱动决策、训练模型、洞察趋势的核心资源。然而,并非所有数据都能通过 API 或数据库直接获取。大量的数据隐藏在 Web 页面中——新闻、商品信息、社交媒体、行业报告等。手动复制粘贴显然不现实,而网络爬虫(Web Crawler)就是…

2026/7/5 20:34:23 阅读更多 →
最简洁yolov8 C++配置教程

最简洁yolov8 C++配置教程

最简洁yolov8 C配置教程ubuntu22.04 安装Cuda TensorRT Cudnn Miniconda1 .Cuda TensorRT Cudnn配置步骤2. Miniconda的安装 在之前的安装完毕且成功的情况下yolov8的C使用1. github上有个大神开源了yolov8的使用,非常好用,[链接](https://github.com/tr…

2026/7/5 20:30:23 阅读更多 →
基于YOLO的计算机视觉项目实战:从数据标注到边缘部署全流程解析

基于YOLO的计算机视觉项目实战:从数据标注到边缘部署全流程解析

🚀 30款热门AI模型一站整合,DeepSeek/GLM/Qwen 随心用,限时 5 折。 👉 点击领海量免费额度 这类项目最值得关注的不是“智能麻将机器人”这个听起来很酷的标题,而是它背后完整的 计算机视觉项目从开发到落地的全流…

2026/7/5 20:28:20 阅读更多 →
如何在无网络环境下快速提取图片文字?Umi-OCR离线文字识别终极指南

如何在无网络环境下快速提取图片文字?Umi-OCR离线文字识别终极指南

如何在无网络环境下快速提取图片文字?Umi-OCR离线文字识别终极指南 【免费下载链接】Umi-OCR OCR software, free and offline. 开源、免费的离线OCR软件。支持截屏/批量导入图片,PDF文档识别,排除水印/页眉页脚,扫描/生成二维码。…

2026/7/5 20:28:20 阅读更多 →
如何让2008年的老款MacBook Pro也能流畅运行macOS Sonoma:OpenCore Legacy Patcher实战指南

如何让2008年的老款MacBook Pro也能流畅运行macOS Sonoma:OpenCore Legacy Patcher实战指南

如何让2008年的老款MacBook Pro也能流畅运行macOS Sonoma:OpenCore Legacy Patcher实战指南 【免费下载链接】OpenCore-Legacy-Patcher Experience macOS just like before 项目地址: https://gitcode.com/GitHub_Trending/op/OpenCore-Legacy-Patcher 还记得…

2026/7/5 20:28:20 阅读更多 →
重塑音频创作边界:Audacity 开源音频编辑器的技术革新与实践指南

重塑音频创作边界:Audacity 开源音频编辑器的技术革新与实践指南

重塑音频创作边界:Audacity 开源音频编辑器的技术革新与实践指南 【免费下载链接】audacity Audio Editor 项目地址: https://gitcode.com/GitHub_Trending/au/audacity 你是否曾为音频编辑软件的复杂操作界面和昂贵许可费用而却步?是否渴望拥有…

2026/7/5 20:26:20 阅读更多 →

日新闻

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容 【免费下载链接】BiliTools A cross-platform bilibili toolbox. 跨平台哔哩哔哩工具箱,支持下载视频、番剧等等各类资源 项目地址: https://gitcode.com/GitHub_Trending/bilit/BiliTools …

2026/7/5 0:03:34 阅读更多 →
威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型的陌生现状在忙碌疲惫的一天里,参与了关于混合后量子密码学的讨论,应付端点攻击找茬的人,还参与留言板讨论后,发现“威胁模型”对多数人仍是陌生概念,且多被当作时髦用语。有趣的相关画作有一幅由 Embyr 创作的…

2026/7/5 0:03:34 阅读更多 →
渗透测试入门指南:从零基础到实战环境搭建

渗透测试入门指南:从零基础到实战环境搭建

1. 从“看热闹”到“入门”:我理解的渗透测试到底是什么?每次看到新闻里说某个大公司的数据被“黑”了,或者某个网站被攻击导致服务瘫痪,你是不是和我一样,心里会冒出两个念头:一是“这黑客真厉害”&#x…

2026/7/5 0:07:38 阅读更多 →

周新闻

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容 【免费下载链接】BiliTools A cross-platform bilibili toolbox. 跨平台哔哩哔哩工具箱,支持下载视频、番剧等等各类资源 项目地址: https://gitcode.com/GitHub_Trending/bilit/BiliTools …

2026/7/5 0:03:34 阅读更多 →
威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型的陌生现状在忙碌疲惫的一天里,参与了关于混合后量子密码学的讨论,应付端点攻击找茬的人,还参与留言板讨论后,发现“威胁模型”对多数人仍是陌生概念,且多被当作时髦用语。有趣的相关画作有一幅由 Embyr 创作的…

2026/7/5 0:03:34 阅读更多 →
渗透测试入门指南:从零基础到实战环境搭建

渗透测试入门指南:从零基础到实战环境搭建

1. 从“看热闹”到“入门”:我理解的渗透测试到底是什么?每次看到新闻里说某个大公司的数据被“黑”了,或者某个网站被攻击导致服务瘫痪,你是不是和我一样,心里会冒出两个念头:一是“这黑客真厉害”&#x…

2026/7/5 0:07:38 阅读更多 →

月新闻