diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c index e8821f7..f953537 100644 --- a/src/backend/access/transam/xact.c +++ b/src/backend/access/transam/xact.c @@ -960,9 +960,6 @@ RecordTransactionCommit(void) } else { - /* - * Begin commit critical section and insert the commit XLOG record. - */ /* Tell bufmgr and smgr to prepare for commit */ BufmgrCommit(); @@ -1046,7 +1043,13 @@ RecordTransactionCommit(void) (void) XLogInsert(RM_XACT_ID, XLOG_XACT_COMMIT, rdata); } - else + /* + * If we created any XLOG entries, we must emit a commit record of + * some kind, but can use the compact format. We also need to do this + * in Hot Standby mode, to avoid confusing the KnownAssignedXids + * machinery. + */ + else if (wrote_xlog || XLogStandbyInfoActive()) { XLogRecData rdata[2]; int lastrdata = 0; @@ -1069,6 +1072,20 @@ RecordTransactionCommit(void) (void) XLogInsert(RM_XACT_ID, XLOG_XACT_COMMIT_COMPACT, rdata); } + else + { + /* + * It seems we don't need a commit record after all. Go ahead + * and mark CLOG without flushing anything. This update might + * get lost if we crash before the pages physically hit the disk, + * but since whatever modifications the transactions made weren't + * WAL-logged either, we won't be losing anything that matters. + * In particular, any temporary or unlogged tables we've written + * will be gone after a crash recovery anyway. + */ + TransactionIdCommitTree(xid, nchildren, children); + goto cleanup; + } } /* @@ -1078,13 +1095,7 @@ RecordTransactionCommit(void) * case can arise if the current transaction wrote only to temporary * and/or unlogged tables. In case of a crash, the loss of such a * transaction will be irrelevant since temp tables will be lost anyway, - * and unlogged tables will be truncated. (Given the foregoing, you might - * think that it would be unnecessary to emit the XLOG record at all in - * this case, but we don't currently try to do that. It would certainly - * cause problems at least in Hot Standby mode, where the - * KnownAssignedXids machinery requires tracking every XID assignment. It - * might be OK to skip it only when wal_level < hot_standby, but for now - * we don't.) + * and unlogged tables will be truncated. * * However, if we're doing cleanup of any non-temp rels or committing any * command that wanted to force sync commit, then we must flush XLOG @@ -1152,6 +1163,7 @@ RecordTransactionCommit(void) TransactionIdAsyncCommitTree(xid, nchildren, children, XactLastRecEnd); } +cleanup: /* * If we entered a commit critical section, leave it now, and let * checkpoints proceed. @@ -1160,10 +1172,10 @@ RecordTransactionCommit(void) { MyProc->inCommit = false; END_CRIT_SECTION(); - } - /* Compute latestXid while we have the child XIDs handy */ - latestXid = TransactionIdLatest(xid, nchildren, children); + /* Compute latestXid while we have the child XIDs handy */ + latestXid = TransactionIdLatest(xid, nchildren, children); + } /* * Wait for synchronous replication, if required. @@ -1171,12 +1183,12 @@ RecordTransactionCommit(void) * Note that at this stage we have marked clog, but still show as running * in the procarray and continue to hold locks. */ - SyncRepWaitForLSN(XactLastRecEnd); + if (wrote_xlog) + SyncRepWaitForLSN(XactLastRecEnd); /* Reset XactLastRecEnd until the next transaction writes something */ XactLastRecEnd.xrecoff = 0; -cleanup: /* Clean up local data */ if (rels) pfree(rels);