searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

PostgreSQL-WAL预写入日志源码分析

2024-05-31 05:34:10
9
0

1、WAL预发式日志写进程

数据库开启后,调用main()->PostmasterMain()->ServerLoop()->StartWalwriter()->

AuxiliaryProcessMain()->WalWriterMain(),开启WalWriter的辅助进程负责wal日志的处理。

 

2、WalWriterMain()函数的主要执行步骤

1、变量初始化

2、注册各种信号函数

3、运行环境初始化

首先,在先前的AuxiliaryProcessMain()函数中,CreateAuxProcessResourceOwner()通过ResourceOwnerCreate函数创建一个名为”Wal Writer”的资源跟踪器 ,为WalWriter创建运行内存上下文。然后在WalWriterMain()函数中,并将运行环境切换到新创建的内存上下文中。

4、注册异常处理函数

5、进入主要的循环程序

首先,处理信号分支,接着,执行XLogBackgroundFlush()函数,负责xlog的写工作。Xlog写工作完成重新进入休眠。

6、WalWriter辅助进程退出。

 

3、XLogBackgroundFlush()函数的主要执行步骤

该函数的主要功能是定位需要写入磁盘的XLog日志的开始位置和结束位置,将其传给XLogWrite()函数。

1、变量初始化,判断数据库系统是否处在恢复状态,是的话就退出该函数。

2、请求获取一个spinlock轻量锁info_lock,在锁的保护下访问日志控制信息XLogCtl。

A、初始化当前请求写入系统缓冲区的日志位置WriteRqst = XLogCtl->LogwrtRqst;

B、初始化当前已经写入系统缓冲区和磁盘中的日志位置LogwrtResult = XLogCtl->

LogwrtResult;

C、把请求写入系统缓冲区的日志位置WriteRqst调整为页尾,使数据能够以页为单位刷新进磁盘,即WriteRqst.Write -= WriteRqst.Write % XLOG_BLCKSZ;

3、通过对WriteRqst.Write 和LogwrtResult.Flush进行比较,确定刷新进磁盘的头尾地址。

A、如果前者大于后者,说明当前的请求有需要刷新入系统缓冲区的日志,进入到第4)步

B、如果前者小于后者,说明当前的请求没有需要刷新入系统缓冲区的日志,需要再多考虑一下的异步日志的情况。在spinlock轻量锁的保护下,将XLogCtl->asyncXactLSN赋值给WriteRqst.Write,然后再次比较WriteRqst.Write 和LogwrtResult.Flush的大小,如果前者依旧小于后者,则退出当前的日志文件,否则进入第4)步。

4、请求获取一个WALWriteLock锁,在该锁的保护下调用XLogWrite()函数进行XLog日志文件的写工作。

 

4、XLogWrite()函数的主要执行步骤

该函数主要功能是根据传入的WriteRqst,进行XLog日志文件的写工作。

1、变量初始化

2、进入主要的程序循环

A、初始化需要刷新到磁盘的最后位置,并且打开相应的日志文件openLogFile,如果不存在该日志文件,则创建一个对应的日志文件。

B、判断当前是否满足以下三个条件之一,转入C,否则转入D 。三个条件分别是:1、 当前位置满一段;2、缓冲区全部刷新到磁盘;3、请求之前的日志记录全部刷新到磁盘

C、刷新缓存到磁盘,执行系统函数_write,将标记位置的日志记录刷新到磁盘(可能是缓冲区)。其中如果满一段,为了减少切换日志段文件带来的开销,应立即执行系统函数_commit强制将日志记录刷新到磁盘(真正的磁盘) ,唤醒WalSender进程和XlogArch日志归档进程,判断是否需要创建检查点。

D、判断这次写是否不足页,如果不足页则更新已经写出的日志位置为当前请求写日志的位置,不足页仅发生在这次写日志写最后一页的时候,因此请求写日志之前的日志已经全部写出,跳出循环。

E、更新需要刷新到磁盘的最后位置为下一页。

3、更新全局变量XLogCtl,释放锁。

0条评论
0 / 1000
f****n
3文章数
0粉丝数
f****n
3 文章 | 0 粉丝
f****n
3文章数
0粉丝数
f****n
3 文章 | 0 粉丝
原创

PostgreSQL-WAL预写入日志源码分析

2024-05-31 05:34:10
9
0

1、WAL预发式日志写进程

数据库开启后,调用main()->PostmasterMain()->ServerLoop()->StartWalwriter()->

AuxiliaryProcessMain()->WalWriterMain(),开启WalWriter的辅助进程负责wal日志的处理。

 

2、WalWriterMain()函数的主要执行步骤

1、变量初始化

2、注册各种信号函数

3、运行环境初始化

首先,在先前的AuxiliaryProcessMain()函数中,CreateAuxProcessResourceOwner()通过ResourceOwnerCreate函数创建一个名为”Wal Writer”的资源跟踪器 ,为WalWriter创建运行内存上下文。然后在WalWriterMain()函数中,并将运行环境切换到新创建的内存上下文中。

4、注册异常处理函数

5、进入主要的循环程序

首先,处理信号分支,接着,执行XLogBackgroundFlush()函数,负责xlog的写工作。Xlog写工作完成重新进入休眠。

6、WalWriter辅助进程退出。

 

3、XLogBackgroundFlush()函数的主要执行步骤

该函数的主要功能是定位需要写入磁盘的XLog日志的开始位置和结束位置,将其传给XLogWrite()函数。

1、变量初始化,判断数据库系统是否处在恢复状态,是的话就退出该函数。

2、请求获取一个spinlock轻量锁info_lock,在锁的保护下访问日志控制信息XLogCtl。

A、初始化当前请求写入系统缓冲区的日志位置WriteRqst = XLogCtl->LogwrtRqst;

B、初始化当前已经写入系统缓冲区和磁盘中的日志位置LogwrtResult = XLogCtl->

LogwrtResult;

C、把请求写入系统缓冲区的日志位置WriteRqst调整为页尾,使数据能够以页为单位刷新进磁盘,即WriteRqst.Write -= WriteRqst.Write % XLOG_BLCKSZ;

3、通过对WriteRqst.Write 和LogwrtResult.Flush进行比较,确定刷新进磁盘的头尾地址。

A、如果前者大于后者,说明当前的请求有需要刷新入系统缓冲区的日志,进入到第4)步

B、如果前者小于后者,说明当前的请求没有需要刷新入系统缓冲区的日志,需要再多考虑一下的异步日志的情况。在spinlock轻量锁的保护下,将XLogCtl->asyncXactLSN赋值给WriteRqst.Write,然后再次比较WriteRqst.Write 和LogwrtResult.Flush的大小,如果前者依旧小于后者,则退出当前的日志文件,否则进入第4)步。

4、请求获取一个WALWriteLock锁,在该锁的保护下调用XLogWrite()函数进行XLog日志文件的写工作。

 

4、XLogWrite()函数的主要执行步骤

该函数主要功能是根据传入的WriteRqst,进行XLog日志文件的写工作。

1、变量初始化

2、进入主要的程序循环

A、初始化需要刷新到磁盘的最后位置,并且打开相应的日志文件openLogFile,如果不存在该日志文件,则创建一个对应的日志文件。

B、判断当前是否满足以下三个条件之一,转入C,否则转入D 。三个条件分别是:1、 当前位置满一段;2、缓冲区全部刷新到磁盘;3、请求之前的日志记录全部刷新到磁盘

C、刷新缓存到磁盘,执行系统函数_write,将标记位置的日志记录刷新到磁盘(可能是缓冲区)。其中如果满一段,为了减少切换日志段文件带来的开销,应立即执行系统函数_commit强制将日志记录刷新到磁盘(真正的磁盘) ,唤醒WalSender进程和XlogArch日志归档进程,判断是否需要创建检查点。

D、判断这次写是否不足页,如果不足页则更新已经写出的日志位置为当前请求写日志的位置,不足页仅发生在这次写日志写最后一页的时候,因此请求写日志之前的日志已经全部写出,跳出循环。

E、更新需要刷新到磁盘的最后位置为下一页。

3、更新全局变量XLogCtl,释放锁。

文章来自个人专栏
云原生消息
3 文章 | 1 订阅
0条评论
0 / 1000
请输入你的评论
0
0