aboutsummaryrefslogtreecommitdiff
path: root/src/backend
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend')
-rw-r--r--src/backend/access/transam/xact.c29
-rw-r--r--src/backend/commands/sequence.c22
2 files changed, 39 insertions, 12 deletions
diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c
index 938c6631fe9..9c848c612cb 100644
--- a/src/backend/access/transam/xact.c
+++ b/src/backend/access/transam/xact.c
@@ -949,10 +949,9 @@ RecordTransactionCommit(void)
/*
* If we didn't create XLOG entries, we're done here; otherwise we
- * should flush those entries the same as a commit record. (An
- * example of a possible record that wouldn't cause an XID to be
- * assigned is a sequence advance record due to nextval() --- we want
- * to flush that to disk before reporting commit.)
+ * should trigger flushing those entries the same as a commit record
+ * would. This will primarily happen for HOT pruning and the like; we
+ * want these to be flushed to disk in due time.
*/
if (!wrote_xlog)
goto cleanup;
@@ -1044,11 +1043,13 @@ RecordTransactionCommit(void)
/*
* Check if we want to commit asynchronously. We can allow the XLOG flush
* to happen asynchronously if synchronous_commit=off, or if the current
- * transaction has not performed any WAL-logged operation. The latter
- * 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
+ * transaction has not performed any WAL-logged operation or didn't assign
+ * a xid. The transaction can end up not writing any WAL, even if it has
+ * a xid, if it only wrote to temporary and/or unlogged tables. It can
+ * end up having written WAL without an xid if it did HOT pruning. In
+ * case of a crash, the loss of such a transaction will be irrelevant;
+ * temp tables will be lost anyway, unlogged tables will be truncated and
+ * HOT pruning will be done again later. (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
@@ -1064,7 +1065,8 @@ RecordTransactionCommit(void)
* if all to-be-deleted tables are temporary though, since they are lost
* anyway if we crash.)
*/
- if ((wrote_xlog && synchronous_commit > SYNCHRONOUS_COMMIT_OFF) ||
+ if ((wrote_xlog && markXidCommitted &&
+ synchronous_commit > SYNCHRONOUS_COMMIT_OFF) ||
forceSyncCommit || nrels > 0)
{
/*
@@ -1136,12 +1138,15 @@ RecordTransactionCommit(void)
latestXid = TransactionIdLatest(xid, nchildren, children);
/*
- * Wait for synchronous replication, if required.
+ * Wait for synchronous replication, if required. Similar to the decision
+ * above about using committing asynchronously we only want to wait if
+ * this backend assigned a xid and wrote WAL. No need to wait if a xid
+ * was assigned due to temporary/unlogged tables or due to HOT pruning.
*
* Note that at this stage we have marked clog, but still show as running
* in the procarray and continue to hold locks.
*/
- if (wrote_xlog)
+ if (wrote_xlog && markXidCommitted)
SyncRepWaitForLSN(XactLastRecEnd);
/* Reset XactLastRecEnd until the next transaction writes something */
diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c
index c4337dd50ea..e44c8783dd4 100644
--- a/src/backend/commands/sequence.c
+++ b/src/backend/commands/sequence.c
@@ -343,6 +343,10 @@ fill_seq_with_data(Relation rel, HeapTuple tuple)
*/
LockBuffer(buf, BUFFER_LOCK_EXCLUSIVE);
+ /* check the comment above nextval_internal()'s equivalent call. */
+ if (RelationNeedsWAL(rel))
+ GetTopTransactionId();
+
START_CRIT_SECTION();
{
@@ -436,6 +440,10 @@ AlterSequence(AlterSeqStmt *stmt)
/* Note that we do not change the currval() state */
elm->cached = elm->last;
+ /* check the comment above nextval_internal()'s equivalent call. */
+ if (RelationNeedsWAL(seqrel))
+ GetTopTransactionId();
+
/* Now okay to update the on-disk tuple */
START_CRIT_SECTION();
@@ -669,6 +677,16 @@ nextval_internal(Oid relid)
last_used_seq = elm;
+ /*
+ * If something needs to be WAL logged, acquire an xid, so this
+ * transaction's commit will trigger a WAL flush and wait for
+ * syncrep. It's sufficient to ensure the toplevel transaction has a xid,
+ * no need to assign xids subxacts, that'll already trigger a appropriate
+ * wait. (Have to do that here, so we're outside the critical section)
+ */
+ if (logit && RelationNeedsWAL(seqrel))
+ GetTopTransactionId();
+
/* ready to change the on-disk (or really, in-buffer) tuple */
START_CRIT_SECTION();
@@ -863,6 +881,10 @@ do_setval(Oid relid, int64 next, bool iscalled)
/* In any case, forget any future cached numbers */
elm->cached = elm->last;
+ /* check the comment above nextval_internal()'s equivalent call. */
+ if (RelationNeedsWAL(seqrel))
+ GetTopTransactionId();
+
/* ready to change the on-disk (or really, in-buffer) tuple */
START_CRIT_SECTION();