`

PostgreSQL启动过程中的那些事十六:启动进程三:CheckPointGuts刷出共享内存里所有数据

阅读更多

 

       话说启动进程调用 StartupXLOG 启动 xlog ,根据情况,如果需要就排除系统故障引起的数据库不一致状态,做相应的 REDO UNDO ,然后创建一个检查点,把所有共享内存磁盘缓冲和提交数据缓冲写并文件同步到磁盘、把检查点插入 xlog 文件、更新控制文件,使数据库达到一种状态

这节接着讨论启动进程在创建检查点时调用的 CheckPointGuts 方法(在创建重启点时也会调用这个方法)。 CheckPointGuts 方法功能是刷出所有共享内存中的数据到磁盘并做文件同步,共享内存中的数据包括 clog subtrans multixact predicate relationmap buffer (数据文件)和 twophase 相关数据。 CheckPointGuts 方法定义和“ CheckPointGuts 方法调用序列图 ”见下面。

 

static void

CheckPointGuts(XLogRecPtr checkPointRedo, int flags)

{

    CheckPointCLOG();

    CheckPointSUBTRANS();

    CheckPointMultiXact();

    CheckPointPredicate();

    CheckPointRelationMap();

    CheckPointBuffers(flags);   /* performs all required fsyncs */

    /* We deliberately delay 2PC checkpointing as long as possible */

    CheckPointTwoPhase(checkPointRedo);

}

 

CheckPointGuts 方法调用序列图

 

CheckPointGuts 方法主要是通过调用提交事务日志管理器的方法 CheckPointClog ,子事务日志管理器的方法 CheckPointSUBTRANS ,多事务日志管理器的方法 CheckPointMultiXact ,支持序列化事务隔离级别的谓词锁模块的方法 CheckPointPredicate ,目录 / 系统表到文件节点映射模块的方法 CheckPointRelationMap ,缓存管理器的方法 CheckPointBuffers ,两阶段提交模块的方法 CheckPointTwoPhase 把共享内存里的数据刷出并文件同步到磁盘。

其中 提交事务日志管理器的方法 CheckPointClog 子事务日志管理器的方法 CheckPointSUBTRANS 、多事务日志管理器的方法 CheckPointMultiXact 、多事务日志管理器的方法 CheckPointMultiXact 、支持序列化事务隔离级别的谓词锁模块的方法 CheckPointPredicate 最后都调用了 SLRU 模块的 SimpleLruFlush 方法,把相关共享内存数据写到磁盘,并调用 pg_fsync 方法把相关内容文件同步到磁盘上对应文件。

在缓存管理器的方法 CheckPointBuffers ,两阶段提交模块的方法 CheckPointTwoPhase 里,因为没有使用 SLRU 算法,直接调用 pg_fsync 方法把相关内容文件同步到磁盘上对应文件。

在目录 / 系统表到文件节点映射模块的方法 CheckPointRelationMap 里,在释放 RelationMappingLock 时,会完成共享内存里相关系统表和对应物理文件映射的文件同步到磁盘工作。

我们看一下各种日志管理,日志对数据库是至关重要的一部分,出现系统故障时,数据库通过重放日志恢复数据,保证数据库一致性和完整性。

Pg 里有 XLOG CLOG SUBTRANS LOG MultiXactID LOG 四种事务日志, XLOG 是事务日志,就是平时常说的 REDOLOG ,记录了事务操作数据库的过程信息和事务最终状态; CLOG XLOG 里事务的提交状态日志; SUBTRANS 是子事务日志, 为每一个事务存储父事务 ID 。这是嵌套事务实现的基础部分, SUBTRANS 仅需要为当前打开的事务记住信息,没有必要在崩溃并重启后保留数据; MultiXactID 是组合事务日志,由一组事务 ID 组成, 是共享行锁 shared-row-lock 实现的基础部分,共享锁锁住的元组在其 Xmax 字段存储 MultiXactId 。各种日志都存放在对应的日志文件里。

有了文件就有了 I/O ,为了降低 I/O 开销, pg 设置了各种日志的缓存区,由对应的日志管理器管理日志的写、文件同步和读等日志维护工作。 Pg 使用简单最近最少使用( SLRU )算法来管理事务日志。使用轻量锁 LWLock ControlLock 锁保护整个缓冲区,其中的每个缓冲块(默认 8K )还有一个 LWLock 锁保护,以控制并发操作。 SLRU 及事务日志的部分相关数据结构在下面。

 

CLOG 控制链接到共享内存数据结构

static SlruCtlData ClogCtlData;

#define ClogCtl (&ClogCtlData)

 

SUBTRANS 控制链接到共享内存数据结构

static SlruCtlData SubTransCtlData;

#define SubTransCtl  (&SubTransCtlData)

 

MultiXact 控制链接到共享内存数据结构

static SlruCtlData MultiXactOffsetCtlData;

static SlruCtlData MultiXactMemberCtlData;

#define MultiXactOffsetCtl   (&MultiXactOffsetCtlData)

#define MultiXactMemberCtl  (&MultiXactMemberCtlData)

 

 

typedef SlruCtlData * SlruCtl ;

 

/* SlruCtlData 是指向共享内存里的活跃信息的非共享结构 */

typedef struct SlruCtlData

{

    SlruShared shared ;

 

    /* 这个标志告诉 是否文件同步写( pg_clog multixact 成员是 true,pg_subtrans pg_notify false */

    bool        do_fsync ;

 

    /* 为截断目的决定两个页号哪一个是更旧的。为了用 包裹 XID 算法( with wraparound XID arithmetic )做正确的事,这儿我们需要用事务 ID 比较 */

    bool        (* PagePrecedes ) ( int , int );

 

    /* SimpleLruInit 期间目录被设置,并且从那以后不变。因为它总是相同的,它不必放到共享内存里。 */

    char        Dir [64];

} SlruCtlData ;

 

共享内存状态

typedef struct SlruSharedData

{

    LWLockId    ControlLock ;

 

    /* 由这个 SLRU 结构管理的缓存块号 */

    int         num_slots ;

 

    /* 持有每一个缓存槽信息的数组。当状态是 EMPTY 缓存页 / 块号是未定义的,当作

page_lru_count */

    char      ** page_buffer ;

    SlruPageStatus * page_status ;

    bool       * page_dirty ;

    int        * page_number ;

    int        * page_lru_count ;

    LWLockId    * buffer_locks ;

 

    /* SLRU / 块里的相关条目的 WAL 刷出 LSN 的可选数组。如果不是 0/NULL ,在写缓存页 / 块前 我们必须刷出 WAL pg_clog true multixact pg_subtrans pg_notify false )。 Group_lsn[] 每缓存页 / 块槽有 lsn_groups_per_page 条目,在这个槽的缓存页 / 块上 SLRU 条目的一个临近组 每一个缓存页 / 块槽 包含最高已知 LSN */

    XLogRecPtr * group_lsn ;

    int         lsn_groups_per_page ;

 

    /* 我们通过设置 page_lru_count[slotno ] = ++cur_lru_count 标记页“最近使用”;最老旧页因此是有表达式 cur_lru_count - page_lru_count[slotno ] 值最高 / 大的那一个。这个数事实上包裹,但这个计算仍然工作 和缓存页 / 块的年龄(超过了 INT_MAX 数)一样长。    */

    int         cur_lru_count ;

 

    /* latest_page_number 是当前日志结尾的页 / 块号;这不是严格的数据,因为我们仅用它避免包裹 swapping 出了最后的页 / 块。 */

    int         latest_page_number ;

} SlruSharedData ;

 

typedef SlruSharedData * SlruShared ;

 

/* 页状态代码。注意这不包含 "dirty" 位。仅在 VALID 或者 WRIT_IN_PROGRESS 状态里 page_dirty 能是 true ;在后面的例子 / 情况里 它暗示 从这次写开始后页又被搞脏 */

typedef enum

{

    SLRU_PAGE_EMPTY ,         /* buffer is not in use */

    SLRU_PAGE_READ_IN_PROGRESS , /* page is being read in */

    SLRU_PAGE_VALID ,         /* page is valid and not being written */

    SLRU_PAGE_WRITE_IN_PROGRESS /* page is being written out */

} SlruPageStatus ;

 

 

SLRU 算法的缓存区操作在下面,其中包括了本节多次调用的 SimpleLruFlush 方法,将缓存数据刷出并文件同步到磁盘。

extern Size SimpleLruShmemSize ( int nslots, int nlsns);

extern void SimpleLruInit ( SlruCtl ctl, const char *name, int nslots, int nlsns,

             LWLockId ctllock, const char *subdir);

extern int SimpleLruZeroPage ( SlruCtl ctl, int pageno);

extern int SimpleLruReadPage ( SlruCtl ctl, int pageno, bool write_ok,

                TransactionId xid);

extern int SimpleLruReadPage_ReadOnly ( SlruCtl ctl, int pageno,

                        TransactionId xid);

extern void SimpleLruWritePage ( SlruCtl ctl, int slotno);

extern void SimpleLruFlush ( SlruCtl ctl, bool checkpoint);

extern void SimpleLruTruncate ( SlruCtl ctl, int cutoffPage);

extern bool SlruScanDirectory ( SlruCtl ctl, int cutoffPage, bool doDeletions);

 

就到这儿吧。

 


------------
转载请著明出处,来自博客:
blog.csdn.net/beiigang
beigang.iteye.com

  • 大小: 46.3 KB
0
0
分享到:
评论

相关推荐

    PostgreSQL中文手册9.2

    一、服务器进程的启动和关闭: 一、服务器进程的启动和关闭: 一、服务器进程的启动和关闭: 一、服务器进程的启动和关闭: 一、服务器进程的启动和关闭: 一、服务器进程的启动和关闭: . 50 PostgreSQL PostgreSQL...

    postgresql--内核分析--多进程结构

    - `src/backend/utils/misc/pg_shmem.c`文件中实现了共享内存的相关功能,这对于多进程之间的通信非常重要。 #### 五、PostgreSQL与MySQL对比 **1. PostgreSQL文件目录组织**: - 整体代码结构清晰,遵循了良好的...

    关于PostGreSQL中的存储过程

    在 PostgreSQL 中,存储过程可以用来实现各种复杂的业务逻辑,例如数据验证、数据转换、业务规则等。 PostgreSQL 中的存储过程 与其他数据库管理系统不同,PostgreSQL 中没有像 MSSql 中的存储过程,但是有一个...

    Go-PostgreSQLBGWorker用Go编写的PostgreSQL后台工作进程

    在PostgreSQL数据库系统中,后台工作进程(Background Worker)是一种扩展其功能的重要机制。这些进程独立于主要的数据库服务器进程运行,允许开发者实现自定义任务,如定期维护、监控或其他后台服务。Go语言以其...

    Postgresql存储过程

    Postgresql存储过程可以用来实现业务逻辑,减少数据库服务器的压力和网络传输的数据量。 一、存储过程结构 一个基本的Postgresql存储过程结构由以下几部分组成: * 过程名:存储过程的名称 * 参数名和类型:定义...

    PostgreSQL_原理简介

    - **共享内存 (Shared Memory)**:所有后端进程之间共享的数据区域。 - **会话进程 (Session Processes)**:每个用户会话都有对应的会话进程。 - **文件存储 (File Storage)**:包括数据文件、索引文件等。 - **实用...

    Linux下PostgreSQL安装与开机启动

    ### Linux下PostgreSQL安装与开机启动详解 #### 1. 添加用户及创建目录 为了确保PostgreSQL服务的安全性,我们通常会为它创建一个独立的系统用户。这一步骤包括了用户创建、密码设定以及相关目录的搭建。 ##### ...

    PostgreSQL博客1

    1. **共享内存**:用于不同后端进程间通信的数据结构,如缓冲区映射表和锁管理器。 2. **工作集内存**:每个后端进程都有自己的一块内存,用于存储查询解析、计划和执行期间使用的数据。 **文件系统** PostgreSQL...

    基于PostgreSQL数据库构建数据中台.pdf

    在构建基于PostgreSQL数据库的数据中台时,企业面临的关键任务是整合、管理和分析大量复杂数据。数据中台作为数据管理的核心,旨在提供高效、灵活的数据服务,满足不同业务场景的需求。以下将详细介绍如何利用...

    PostgreSQL修炼之道 从小工到专家.pptx

    PostgreSQL修炼之道:从小工到专家 PostgreSQL是一种功能强大且广泛应用的开源关系型数据库管理系统,本书《PostgreSQL修炼之道:从小工到专家》旨在帮助读者深入理解PostgreSQL的核心原理和最佳实践,从而提升...

    postgresql数据快速倒入redis

    - **数据一致性**:在导入过程中如何保证PostgreSQL和Redis之间的数据一致性?这可能需要使用事务或乐观锁来确保。 - **内存管理**:Redis是内存数据库,大量数据导入可能导致内存不足。因此,需要合理规划Redis的...

    linux配置postgresql

    在 Linux 系统中,可以通过以下命令启动 PostgreSQL: ``` # su – postgres pg$ /usr/local/pgsql/bin/postmaster ``` 这将启动 PostgreSQL 数据库服务器,并允许用户访问数据库。 配置 PostgreSQL 数据库需要多个...

    jeecgboot(postgreSQL).pdf

    url: jdbc:postgresql://localhost:5432/postgres username: postgres password: root driver-class-name: org.postgresql.Driver ``` 此外,还需要添加 Druid 配置,以便监控数据库连接池的状态: ```...

    Postgresql存储过程.docx

    PostgreSQL 存储过程详解 PostgreSQL 存储过程是一种强大的功能,可以实现复杂的逻辑操作和数据处理。下面将详细介绍 PostgreSQL 存储过程的结构、变量类型、连接字符、控制结构等知识点。 一、存储过程结构 存储...

    如何恢复PostgreSQL数据库

    PostgreSQL 是一个功能强大且广泛使用的开源关系数据库管理系统,但是在实际应用中,数据库崩溃或无法启动的情况时有发生。这时,如何恢复 PostgreSQL 数据库变得非常重要。下面将详细介绍如何恢复 PostgreSQL ...

    postgresql-42.3.1-API文档-中文版.zip

    Maven坐标:org.postgresql:postgresql:42.3.1; 标签:postgresql、中文文档、jar包、java; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化翻译,文档中的代码和结构...

    postgreSQL数据迁移到达梦数据库操作

    PostgreSQL 数据迁移到达梦数据库操作是指将 PostgreSQL 数据库中的数据迁移到达梦数据库中的过程。该过程需要使用 Navicat for PostgreSql 工具生成 SQL 脚本,然后使用达梦数据库的控制台工具 DM 控制台工具来执行...

    PostgreSQL 14.1 中文手册

    PostgreSQL 14.1 手册 PostgreSQL 全球开发组 翻译:彭煜玮1,PostgreSQL中文社区2文档翻译组

    MySQL数据迁移到postgresql必备手册.pdf

    - **数据兼容性** MySQL和PostgreSQL的数据类型可能存在差异,迁移前需确保所有数据类型都能在目标数据库中找到对应的映射。 - **权限设置** 确保你有足够权限在目标数据库上创建新对象和导入数据。 - **完整性...

Global site tag (gtag.js) - Google Analytics