PostgreSQL备机checkpoint
数据库异常关闭时,数据库关闭时来不及或者没机会做checkpoint,则需要从上一个一致性检查的开始恢复。
? ? PostgreSQL备机checkpoint是不能产生checkpoint WAL的,因为如果写这样类型的checkpoint的话,就会将接收的WAL打乱,那么日志将混乱,回放会出问题。 ? ? 那么问题来了,备机支持checkpoint吗?他的checkpoint怎么做的? ? ? PostgreSQL为了缩短恢复时间,备机上也支持checkpoint,即CreateRestartPoint。但是其pg_control文件的checkpoint记录的位点是从主机传过来WAL里面的checkpoint记录位置。 1、备机回放 StartupXLOG do{ ... RmgrTable[record->xl_rmid].rm_redo(xlogreader);//回放 ... record = ReadRecord(xlogreader,InvalidXLogRecPtr,LOG,false);//读取一个xlog } while (record != NULL); 2、回放函数 void xlog_redo(XLogReaderState *record) { ... else if (info == XLOG_CHECKPOINT_SHUTDOWN){ ... memcpy(&checkPoint,XLogRecGetData(record),sizeof(CheckPoint)); ... RecoveryRestartPoint(&checkPoint); }else if (info == XLOG_CHECKPOINT_ONLINE){ ... memcpy(&checkPoint,sizeof(CheckPoint)); ... RecoveryRestartPoint(&checkPoint); } ... } 3、RecoveryRestartPoint static void RecoveryRestartPoint(const CheckPoint *checkPoint) { ... SpinLockAcquire(&XLogCtl->info_lck); XLogCtl->lastCheckPointRecPtr = ReadRecPtr;//ReadRecPtr为读取checkpoint记录后的位置 XLogCtl->lastCheckPointEndPtr = EndRecPtr; XLogCtl->lastCheckPoint = *checkPoint; SpinLockRelease(&XLogCtl->info_lck); } 4、ReadRecPtr赋值 ReadRecord for (;;) { char *errormsg; record = XLogReadRecord(xlogreader,RecPtr,&errormsg); ReadRecPtr = xlogreader->ReadRecPtr; EndRecPtr = xlogreader->EndRecPtr; ... } 5、备机createcheckpoint bool CreateRestartPoint(int flags) { LWLockAcquire(CheckpointLock,LW_EXCLUSIVE); /* Get a local copy of the last safe checkpoint record. */ SpinLockAcquire(&XLogCtl->info_lck); lastCheckPointRecPtr = XLogCtl->lastCheckPointRecPtr;//checkpoint的位置来自XLogCtl->lastCheckPointRecPtr lastCheckPointEndPtr = XLogCtl->lastCheckPointEndPtr; lastCheckPoint = XLogCtl->lastCheckPoint; SpinLockRelease(&XLogCtl->info_lck); ... if (XLogRecPtrIsInvalid(lastCheckPointRecPtr) || lastCheckPoint.redo <= ControlFile->checkPointCopy.redo){ //回放了最后一个checkpoint记录后,备机再次手动执行checkpoint命令 UpdateMinRecoveryPoint(InvalidXLogRecPtr,true); if (flags & CHECKPOINT_IS_SHUTDOWN){ LWLockAcquire(ControlFileLock,LW_EXCLUSIVE); ControlFile->state = DB_SHUTDOWNED_IN_RECOVERY; ControlFile->time = (pg_time_t) time(NULL); UpdateControlFile(); LWLockRelease(ControlFileLock); } LWLockRelease(CheckpointLock); return false; } ... LWLockAcquire(ControlFileLock,LW_EXCLUSIVE); if (ControlFile->state == DB_IN_ARCHIVE_RECOVERY && ControlFile->checkPointCopy.redo < lastCheckPoint.redo){ ControlFile->prevCheckPoint = ControlFile->checkPoint; ControlFile->checkPoint = lastCheckPointRecPtr;//checkpoint的位置 ControlFile->checkPointCopy = lastCheckPoint; ControlFile->time = (pg_time_t) time(NULL); ... if (flags & CHECKPOINT_IS_SHUTDOWN) ControlFile->state = DB_SHUTDOWNED_IN_RECOVERY; UpdateControlFile(); } ... return true; } 6、备机shutdown void ShutdownXLOG(int code,Datum arg) { /* * Signal walsenders to move to stopping state. */ WalSndInitStopping(); /* * Wait for WAL senders to be in stopping state. This prevents commands * from writing new WAL. */ WalSndWaitStopping(); if (RecoveryInProgress())//备机写checkpoint CreateRestartPoint(CHECKPOINT_IS_SHUTDOWN | CHECKPOINT_IMMEDIATE); else { /* * If archiving is enabled,rotate the last XLOG file so that all the * remaining records are archived (postmaster wakes up the archiver * process one more time at the end of shutdown). The checkpoint * record will go to the next XLOG file and won‘t be archived (yet). */ if (XLogArchivingActive() && XLogArchiveCommandSet()) RequestXLogSwitch(false); CreateCheckPoint(CHECKPOINT_IS_SHUTDOWN | CHECKPOINT_IMMEDIATE); } ShutdownCLOG(); ShutdownCommitTs(); ShutdownSUBTRANS(); ShutdownMultiXact(); } 7、总结 PostgreSQL备库也可以写检查点,目的是避免每次重启备库都需要从上一个检查点(由主库产生,在WAL中回放出来的)APPLY后面所有的WAL。但是他记录的checkpoint位点是从主库传过来的。这样的话就有问题了,如果主机很长时间都没有做checkpoint了,备机即使正常关闭,重启时,也会从上一个checkpoint开始恢复,这样也会恢复很长时间;并且多次重启也需要从上一次checkpoint开始重复恢复。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- 关于获取Flex Mobile屏幕宽高
- haskell – yesod-bin缺少(未知)依赖?
- c – 如何捕获属性表中的“tab changed”事件
- 使用swift开发Cordova插件
- Vue.js第一天学习笔记(数据的双向绑定、常用指令)
- reactjs – 设置babel-plugin-styled-components Typescrip
- Swift 3核心数据 – NSExpression forFunction:“sum:”抛
- Cannot find module node_sqlite3.node
- 如何利用Truffle React框架构建完整的智能合约
- cocos2dx-lua中带有‘\0’数据的字符串传递