这节主要讨论启动进程到了StartupXLOG。根据情况,如果需要就排除系统故障引起的数据库不一致状态,做相应的REDO或UNDO,然后创建一个检查点,把所有共享内存磁盘缓冲和提交数据缓冲写并文件同步到磁盘、把检查点插入xlog文件、更新控制文件,使数据库达到一种状态,设置共享内存中XLogCtl、ShmemVariableCache等对象信息;如果不需要,就根据控制文件从xlog文件读取最后的检查点信息,设置共享内存中XLogCtl、ShmemVariableCache等对象信息;启动完XLOG,启动进程完成使命,自己做了了断,postmaster进程根据子进程结束信号响应句柄继续。
目前没有看到数据文件里记录了检查点,难道这个没有???
3
先上个图方法调用序列示意图
4
上StartupXLog方法的处理流程示意图
数据库在什么情况下需要恢复。如果出现事务故障、系统故障或者介质故障时,数据库需要恢复。出现诸如运算溢出、死锁、违反完整性约束等事务故障时数据库在运行时可以通过强制回滚自行处理。系统故障是主存数据丢失,未完成事务有些数据已写到物理数据库,此时数据库启动时需要事务回滚(UNDO/rollback)恢复。已完成事务有些或全部数据未写到物理数据库,此时数据库启动时需要重做(REDO)已提交事务。介质故障,需要从以前的备份做专门恢复。
话说到了XLogStartup方法,在这个方法里最主要的是根据情况判断是否需要恢复。如果不需要恢复,处理比较简单;如果需要恢复,根据不同状况做相应恢复。这儿这个状况就是判断系统是否在上次关闭时出现了系统故障。
XLogStartup方法,先读取控制文件pg_control到ControlFileData数据结构,再看是否有恢复命令文件recovery.conf(判断是否是归档模式,如果归档模式,需要恢复的话,就是归档恢复),读取内容并设置InArchiveRecovery = true,并根据情况,如果是hot standby的从系统,设置StandbyMode = true。接着读时间线历史文件。然后把来自控制文件的恢复目标时间线recoveryTargetTLI和归档清楚命令archive_cleanup_command保存于共享内存中的xlog控制结构XLogCtl的相关成员里以备其它进程查看。接着调用read_backup_label方法,看是否有备份标签文件$PGDATA$/backup_label,如果有,从中取检查点记录位置赋给checkPointLoc,如果没有备份标签文件,把控制文件里的检查点位置赋给checkPointLoc。根据这个检查点位置指针checkPointLoc从xlog文件中读这个检查点的xlog记录解析到检查点对象checkpoint。根据其自身位置指针和其记录的下一个xlog记录位置指针,或者控制文件记录的数据库是否非正常关闭状态或(ControlFile->state != DB_SHUTDOWNED)者有无recover.conf文件,判断是否需要恢复。
如果不需要恢复,更新控制文件的state等于DB_IN_PRODUCTION,time等于系统当前时间。接着设置共享内存里的XLogCtl的成员Write.lastSegSwitchTime为当前时间,根据控制文件初始化XLogCtl的最后的检查点的XID/epoch,再初始化共享内存里缓存变量结构ShmemVariableCache的latestCompletedXid以备份事务ID(ShmemVariableCache->latestCompletedXid = ShmemVariableCache->nextXid)然后调用RecoverPreparedTransactions()扫描pg_twophase文件夹重新为已准备好的事务加载共享内存状态。如果任何关键GUC参数改变了,在我们允许backend进程写WAL日志以前记录到日志。所有这些事搞定后,设置xlogctl->SharedRecoveryInProgress= false允许backend进程写WAL日志。然后退出启动进程,postmaster进程响应子进程退出信号其它相关进程。
如果需要恢复。这儿要处理的是崩溃时刻未完成事务已写入物理数据库的事务(处理方法是UNDO)和崩溃时刻已完成事务未写入物理数据库的事务(处理方法是REDO)。
根据数据库的运行模式(有无起归档,有无hot standby。有hot standby时,其主系统恢复和启归档情况一样进行恢复,从系统单独处理),调用ReadRecord方法从不同地方读取xlog日志记录,调用xlog的资源管理器xmgr的相应资源的重放方法做恢复。恢复完成后剩余步骤和不需要恢复的情况一样,处理后续事宜。然后退出启动进程,postmaster进程响应子进程退出信号其它相关进程。略详细过程见“XLogStartup流程示意图”
相关主要结构见下面:
控制文件的结构ControlFileData及检查点结构CheckPoint参见《PostgreSQL存储系统一:控制文件存储结构》。
XLog日志文件相关结构参见《PostgreSQL存储系统二:REDOLOG文件存储结构》。
VariableCache是共享内存里用来跟踪OID和XID分配状态的数据结构。由于历史原因,由不同的轻量锁LWLock保护这个结构中不同的字段。
typedefstruct VariableCacheData
{
/*这些字段由OidGenLock锁保护 */
Oid nextOid; /* next OID to assign */
uint32 oidCount; /* OIDs available before must do XLOG work */
/*这些字段由XidGenLock锁保护 */
TransactionIdnextXid