1.3.2.2主要函数分析:
XLogInsert的执行步骤
功能:插入一条XLOG记录,记录有特殊的RMID标识和附带信息字节,记录的主体包括数据块和数据链。 返回XLOG指针(指向记录尾的),可以用做已经存入日志的数据页的LSN,根据LSN,XLOG在修改实际数据之前先写日志(也就是WAL)。
执行步骤:
1. 计算日志记录的长度
2. 判断是否该日志记录是否会写入新的日志段中
如果是,调用XLogWrite,把当前缓冲区中的所有日志写入磁盘中。也就是把属于旧日志段、且尚未写入旧日志段的日志记录写入磁盘中
3. 将这条日志记录写入日志缓冲区中。
a) 如果当前缓冲区的剩余空间无法容纳这条日志记录。
i. 我们先将这条日志记录中的前一部分写入当前缓冲区中。
ii. 调用AdvanceXLInsertBuffer,将下一个缓冲区清空(如果这个缓冲区中的数据还未写入磁盘中,调用XLogWrite,将此缓冲区的数据写入磁盘)
iii. 将日志记录的剩余部分写入刚清空的缓冲区。
4. 如果需要进行日志的切换(切换条件为:rmid == RM_XLOG_ID && info == XLOG_SWITCH),则调用“XLogWrite”写出xlog缓存中的所有内容,然后切换成新的段文件,更新xlog共享缓存等信息。
切换段文件的主要代码为:AdvanceXLInsertBuffer(true);
5.
说明:
分析XlogInsert()函数,可以看出需要写日志的操作有:
可操作对象 可执行的操作
数据库: 创建数据库
表空间: 建立、删除
堆(数据操作等): 插入、删除、更新、释放
索引(B树、gin等): 新建、插入、分裂、建立新根、读取根、删除项、删除页
序列: 定义、修改、读取值、设置值
存储区管理: 建立、截断
事务: 提交、中断、子事务的中断
检查点: 建立
XLogFlush的执行步骤
功能:保证给出位置上的XLOG日志数据被写(flush)到了磁盘上
注意:不同于XLogWrite,这个函数要尽量避免请求日志写锁(WALWriteLock)。
调用XlogFlush()的函数如图:
刷出日志的时机 图:根据调用关系配合代码即可知预先日志的原理
XLogWrite的执行步骤
功能:把xlog日志中的内容写出内存
执行步骤:
1.循环判断当前所请求的日志记录是否已写入磁盘,如果不是,执行下列操作,否则跳到第2步
a) 如果本进程最后一次写日志时的logid和segid与系统当前的logid和segid不符
i. 关闭xlog日志文件(通过调用“XLogFileClose”),创建或打开系统当前logid和segid对应的日志段文件(通过调用“XLogFileInit”),更新控制文件的内容(通过调用“UpdateControlFile”)。
ii. 如果系统当前segid和上一次作checkpoint时的segid相比,超过CheckPointSegments个;或者当“RedoRecPtr”中记载的“xlogid”与当前的“openXlogId”相比不一致,表明其所保存的旧的信息已经很久了,需要做chencpoint,故调用“RequestCheckpoint”,请求bgwrite进程进行创建检查点操作。
iii. 调用“pwrite”把xlog中应该写到外存中的信息写出去
iv. 如果现在所写的缓冲区对应当前日志段的最后一页、或者用户强制要求日志段转换,则调用“issue_xlog_fsync”根据同步的参数(“postgres.conf”文件中提供了相应的GUC参数)同步日志文件;
v. 如果上一条成立,且处于归档模式,在”archive_status”目录下,产生一个文件,作为用于通知可以进行归档文件的标志,并发信号通知归档进程可以进行归档了。其文件名称是日志段的名称+”.ready”,例如” 000000010000000000000000”.ready
2.执行fsnc
3.修改xlog的共享内存状态