同步複製情況下,先刷寫日誌,然後記錄clog並持久化,最後纔等待備機接收日誌後返回的ACK,如果備機有問題的話或複製鏈路異常,日誌傳輸失敗,此時用戶客戶端的commit會掛住,一旦主機異常宕機重啓後,這個異常的事務會從日誌中恢復出來,因爲事務在日誌中顯示已提交,而相對客戶而言是未提交的。這一點需要注意。
RecordTransactionCommit
if ((wrote_xlog && markXidCommitted &&
synchronous_commit > SYNCHRONOUS_COMMIT_OFF) ||
forceSyncCommit || nrels > 0){//同步
XLogFlush(XactLastRecEnd);
/*
* Now we may update the CLOG, if we wrote a COMMIT record above
*/
if (markXidCommitted)
TransactionIdCommitTree(xid, nchildren, children);
}else{
XLogSetAsyncXactLSN(XactLastRecEnd);
if (markXidCommitted)
TransactionIdAsyncCommitTree(xid, nchildren, children, XactLastRecEnd);
}
...
if (wrote_xlog && markXidCommitted)
SyncRepWaitForLSN(XactLastRecEnd, true);
|-- if (!SyncRepRequested())
| return;
| for(;;){
| 等待確認
|-- }
...
//同步複製
#define SyncRepRequested() \
(max_wal_senders > 0 && synchronous_commit > SYNCHRONOUS_COMMIT_LOCAL_FLUSH)