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);
