本文共 3003 字,大约阅读时间需要 10 分钟。
前面说明了pg中同步复制的设置方法,主要是设置参数synchronous_commit和synchronous_standby_names,下面介绍同步复制的代码实现流程(这里先介绍PG9.6之前的同步复制方式,即只支持一个同步备机)。
同步复制的源代码在pg中的位置为src/backend/replication/syncrep.c,该程序中包含的函数主要分为三部分:
if (!SyncRepRequested() || !SyncStandbysDefined()) return;步骤2:判断全局变量中sync_standbys_defined是否定义,该变量表示是否设置全局变量,在checkpoint进程中更新该字段, 同时检查当前的LSN与全局变量中记录的等待LSN之间的关系,如果提交的LSN小于或者等于记录的等待等待提交LSN,表明已经接收到备机的响应,无须等待
if (!WalSndCtl->sync_standbys_defined || XLByteLE(XactCommitLSN, WalSndCtl->lsn[mode])) { LWLockRelease(SyncRepLock); return; }
MyProc->waitLSN = XactCommitLSN; MyProc->syncRepState = SYNC_REP_WAITING; SyncRepQueueInsert(mode);步骤4:一直等待同步复制状态的更新,如果为SYNC_REP_WAIT_COMPLETE,表示备机已经作出响应,在备机上提交完成
if (syncRepState == SYNC_REP_WAIT_COMPLETE) break;
if (MyWalSnd->sync_standby_priority == 0 || MyWalSnd->state < WALSNDSTATE_STREAMING || XLogRecPtrIsInvalid(MyWalSnd->flush)) return;step2:判断是否为同步复制进程(PG9.6之前的版本只支持一个同步备)
for (i = 0; i < max_wal_senders; i++) { /* use volatile pointer to prevent code rearrangement */ volatile WalSnd *walsnd = &walsndctl->walsnds[i]; if (walsnd->pid != 0 && walsnd->state == WALSNDSTATE_STREAMING && walsnd->sync_standby_priority > 0 && (priority == 0 || priority > walsnd->sync_standby_priority) && !XLogRecPtrIsInvalid(walsnd->flush)) { priority = walsnd->sync_standby_priority; syncWalSnd = walsnd; } }对所有的walsender进程循环判断,找到最高优先级对应的walsender进程。然后判断当前进程是否为同步复制
if (syncWalSnd != MyWalSnd) { LWLockRelease(SyncRepLock); announce_next_takeover = true; return; }step3:如果Wie同步复制模式,唤醒等待的队列
/* * Set the lsn first so that when we wake backends they will release up to * this location. */ if (XLByteLT(walsndctl->lsn[SYNC_REP_WAIT_WRITE], MyWalSnd->write)) { walsndctl->lsn[SYNC_REP_WAIT_WRITE] = MyWalSnd->write; numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE); } if (XLByteLT(walsndctl->lsn[SYNC_REP_WAIT_FLUSH], MyWalSnd->flush)) { walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = MyWalSnd->flush; numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH); }在唤醒同步等待队列函数SyncRepWakeQueue中,改变同步复制的状态。
转载地址:http://xibgi.baihongyu.com/