MULTIXACT日志管理器

模块概述

MULTIXACT(Multi-Transaction,组合事务)日志是PostgreSQL为适配多版本并发控制(MVCC) 下的行共享锁场景设计的核心模块:当同一个数据元组关联多个事务ID(XID)时,为简化锁的统一操作,PostgreSQL将这些XID组合映射为一个唯一的MultiXactID,MULTIXACT日志管理器负责维护这种“多XID→单MultiXactID”的映射关系。

该模块与CLOG、SUBTRANS日志的核心共性是基于SLRU(Simple LRU)缓冲池 实现内存管理;核心差异是MULTIXACT需同时维护“偏移量+成员”两类信息,因此使用两个独立的SLRU缓冲池 分别管理,且日志需持久化(与SUBTRANS不同)、需与XLOG交互(保证崩溃恢复)。

1. 核心数据结构与日志定位规则
1.1 MultiXactID的映射关系

MultiXactID是“多XID→单ID”的映射标识,需存储两类核心信息来关联XID集合(还原原文档图7-10的核心逻辑):

  • Offset(偏移量):标记XID数组中该MultiXactID对应的起始位置;
  • nMembers(成员数量):标记该MultiXactID关联的XID总数。

Id2/Id4/Id3

Id5/Id7/Id6

事务ID队列

Offset1 → nM1 → MultiXactID1

Offset3 → nM3 → MultiXactID3

注:图7-10 MultiXactID组合关系

1.2 核心数据结构定义
(1)MultiXactStateData:MultiXactID分配管理结构

该结构用于维护MultiXactID的全局分配状态,修正原文档格式错误后的完整定义:

// 数据结构7.25 MultiXactStateData
typedef struct MultiXactStateData
{
    MultiXactId nextMXact;          // 下一个可分配的MultiXactID
    MultiXactOffset nextOffset;     // 下一个MultiXactID对应的起始偏移量
    MultiXactId lastTruncationPoint;// 上一次清理(截断)的位置
    MultiXactId perBackendXactIds[1];// MultiXactID队列起始位置
} MultiXactStateData;
(2)mXactCacheEnt:MultiXactID本地缓存结构

该结构定义操作MultiXactID的统一接口,用于本地缓存“MultiXactID→XID集合”的映射关系,修正格式错误后的完整定义:

// 数据结构7.26 mXactCacheEnt
typedef struct mXactCacheEnt
{
    struct mXactCacheEnt *next;     // 缓存链表下一个节点
    MultiXactId multi;              // 组合事务ID
    int nxids;                      // 关联的XID数量
    TransactionId xids[1];          // 关联的XID数组(柔性数组)
} mXactCacheEnt;
1.3 存储路径与定位规则
(1)存储路径

MULTIXACT日志文件存储于 PGDATA/pg_multixact 目录下,包含两个子目录,分工明确:

  • members:存储MultiXactID关联的XID成员列表;
  • offsets:存储MultiXactID对应的偏移量(Offset)和成员数(nMembers)。
(2)定位宏定义(修正原文档语法/拼写错误)

通过MultiXactID可计算其在offsets目录的存储位置,通过偏移量可计算其在members目录的存储位置,核心宏定义如下:

宏定义 功能 修正后完整定义
MultiXactIdToOffsetPage(xid) 根据MultiXactID计算其在offsets目录的页面号 `#define MultiXactIdToOffsetPage(xid) \
((xid) / (MultiXactOffset)MULTIXACT_OFFSETS_PER_PAGE)`
MultiXactIdToOffsetEntry(xid) 根据MultiXactID计算其在offsets页面内的偏移 `#define MultiXactIdToOffsetEntry(xid) \
((xid) % (MultiXactOffset)MULTIXACT_OFFSETS_PER_PAGE)`
MXOffsetToMemberPage(xid) 根据偏移量计算其在members目录的页面号 `#define MXOffsetToMemberPage(xid) \
((xid) / (TransactionId)MULTIXACT_MEMBERS_PER_PAGE)`
MXOffsetToMemberEntry(xid) 根据偏移量计算其在members页面内的偏移 `#define MXOffsetToMemberEntry(xid) \
((xid) & (TransactionId)MULTIXACT_MEMBERS_PER_PAGE)`
1.4 缓冲池控制结构

MULTIXACT日志管理器使用两个独立的SLRU缓冲池 管理日志(区别于CLOG/SUBTRANS的单缓冲池),均为Postmaster启动后注册的全局共享内存对象:

  • MultiXactOffsetCtl:管理offsets目录的日志页面(偏移量+成员数);
  • MultiXactMemberCtl:管理members目录的日志页面(XID成员列表);
    两个缓冲池协同维护全局MultiXactID的内存映射,保证多进程并发访问的一致性。
2. 核心操作说明

MULTIXACT日志管理器的核心操作包括MultiXactID的生命周期管理(创建/扩增)、日志系统的启停/检查点等,其中启停/检查点需同时操作两个SLRU缓冲池,核心操作如下:

2.1 MultiXactID创建(MultiXactIdCreate)

功能:将多个XID组合为一个MultiXactID,返回该标识以统一管理行共享锁相关操作。
核心流程

  1. 本地缓存检查:在当前进程的MXactCache中查询该XID组合是否已生成过MultiXactID,若存在则直接返回;
  2. 分配新ID:调用GetNewMultiXactId从共享内存的MultiXactState中获取新的MultiXactID,并更新nextMXact(下一个可分配ID)和nextOffset(下一个起始偏移量);
  3. 记录XLOG:向XLOG写入操作日志,记录本次分配的MultiXactID、关联的XID链表及XID数量(保证崩溃后可恢复);
  4. 更新缓存并返回:将“MultiXactID→XID集合”的映射关系更新到本地MXactCache,返回新生成的MultiXactID。
2.2 MultiXactID扩增(MultiXactIdExpand)

功能:向已有MultiXactID关联的XID队列中新增一个XID,实现MultiXactID的扩容。
核心流程

  1. 查找关联信息:通过MultiXactID找到其对应的XID队列和XID数量;
  2. 边界校验1:若该MultiXactID无关联XID成员,直接创建仅包含新增XID的MultiXactID并返回;
  3. 边界校验2:若新增XID已存在于当前XID队列中,直接返回原MultiXactID;
  4. 扩容并重建:取出该MultiXactID对应的XID链表,将新增XID追加至链表末尾,调用MultiXactIdCreate生成新的MultiXactID并返回。
2.3 运行状态检测(MultiXactIdIsRunning)

功能:判断一个MultiXactID是否处于“运行中”状态,用于行锁有效性校验。
核心逻辑:遍历该MultiXactID关联的所有XID,若任意一个XID属于当前事务或正在运行,则判定该MultiXactID处于运行中。

2.4 日志系统启动(StartupMultiXact)

触发时机:Postmaster启动时,通过StartupXlog间接调用。
核心功能:初始化MultiXactOffsetCtlMultiXactMemberCtl两个SLRU缓冲池,为MultiXactID管理提供基础内存环境。

2.5 日志系统关闭(ShutdownMultiXact)

功能:安全关闭MULTIXACT日志系统。
核心逻辑:调用SimpleLruFlushMultiXactOffsetCtlMultiXactMemberCtl两个缓冲池中的所有脏页刷盘,保证日志数据持久化。

2.6 检查点操作(CheckPointMultiXact)

触发时机:数据库执行检查点时调用。
核心功能:将两个SLRU缓冲池的脏页刷盘;与“关闭操作”的核心差异是:刷盘过程中允许其他进程向缓冲池写入日志(保证检查点期间系统可用性)。

总结

  1. 核心定位:MULTIXACT日志管理器通过“双SLRU缓冲池”维护“多XID→单MultiXactID”的映射关系,解决MVCC下行共享锁的多XID统一操作问题;
  2. 核心特性:需与XLOG交互保证持久化,支持MultiXactID的创建/扩增,检测运行状态时需遍历关联的所有XID;
  3. 操作关键:启停/检查点需同时操作“偏移量+成员”两个SLRU缓冲池,检查点刷盘时允许并发写操作(区别于关闭操作)。
Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐