{
XactLockTableWait(transactionId, NULL, NULL, XLTW_None);
commitlsn = CLogGetCommitLSN(transactionId);
+
+ /*
+ * FIXME: It's possible that the backend crashed and left the
+ * clog in COMMITTING state.
+ */
Assert(!COMMITLSN_IS_COMMITTING(commitlsn));
}
* a specified transaction id.
*
* TransactionIdCommitTree
- * TransactionIdAsyncCommitTree
* TransactionIdAbortTree
* ========
* these functions set the transaction status of the specified
TransactionIdSetCommitLSN(xid, nxids, xids, lsn);
}
-/*
- * TransactionIdAsyncCommitTree
- * Same as above, but for async commits. The commit record LSN is needed.
- *
- * XXX: there is no difference ATM
- */
-void
-TransactionIdAsyncCommitTree(TransactionId xid, int nxids, TransactionId *xids,
- XLogRecPtr lsn)
-{
- TransactionIdSetCommitLSN(xid, nxids, xids, lsn);
-}
-
/*
* TransactionIdAbortTree
* Marks the given transaction and children as aborted.
static void CheckTransactionChain(bool isTopLevel, bool throwError,
const char *stmtType);
static void CommitTransaction(void);
-static TransactionId RecordTransactionAbort(bool isSubXact);
+static void RecordTransactionAbort(bool isSubXact);
static void StartTransaction(void);
static void StartSubTransaction(void);
/*
* RecordTransactionCommit
- *
- * Returns latest XID among xact and its children, or InvalidTransactionId
- * if the xact has no XID. (We compute that here just because it's easier.)
*/
-static TransactionId
+static void
RecordTransactionCommit(void)
{
TransactionId xid = GetTopTransactionIdIfAny();
bool markXidCommitted = TransactionIdIsValid(xid);
- TransactionId latestXid = InvalidTransactionId;
int nrels;
RelFileNode *rels;
int nchildren;
forceSyncCommit || nrels > 0)
{
XLogFlush(XactLastRecEnd);
-
- /*
- * Now we may update the CLOG, if we wrote a COMMIT record above
- */
- if (markXidCommitted)
- TransactionIdCommitTree(xid, nchildren, children, XactLastRecEnd);
}
else
{
* flush this commit.
*/
XLogSetAsyncXactLSN(XactLastRecEnd);
-
- /*
- * We must not immediately update the CLOG, since we didn't flush the
- * XLOG. Instead, we store the LSN up to which the XLOG must be
- * flushed before the CLOG may be updated.
- */
- if (markXidCommitted)
- TransactionIdAsyncCommitTree(xid, nchildren, children, XactLastRecEnd);
}
+ /*
+ * Now we may update the CLOG, if we wrote a COMMIT record above
+ */
+ if (markXidCommitted)
+ TransactionIdCommitTree(xid, nchildren, children, XactLastRecEnd);
+
/*
* If we entered a commit critical section, leave it now, and let
* checkpoints proceed.
END_CRIT_SECTION();
}
- /* Compute latestXid while we have the child XIDs handy */
- latestXid = TransactionIdLatest(xid, nchildren, children);
-
/*
* Wait for synchronous replication, if required.
*
/* Clean up local data */
if (rels)
pfree(rels);
-
- return latestXid;
}
/*
* RecordTransactionAbort
- *
- * Returns latest XID among xact and its children, or InvalidTransactionId
- * if the xact has no XID. (We compute that here just because it's easier.)
*/
-static TransactionId
+static void
RecordTransactionAbort(bool isSubXact)
{
TransactionId xid = GetCurrentTransactionIdIfAny();
- TransactionId latestXid;
int nrels;
RelFileNode *rels;
int nchildren;
/* Reset XactLastRecEnd until the next transaction writes something */
if (!isSubXact)
XactLastRecEnd = 0;
- return InvalidTransactionId;
+ return;
}
/*
END_CRIT_SECTION();
- /* Compute latestXid while we have the child XIDs handy */
- latestXid = TransactionIdLatest(xid, nchildren, children);
-
/* Reset XactLastRecEnd until the next transaction writes something */
if (!isSubXact)
XactLastRecEnd = 0;
/* And clean up local data */
if (rels)
pfree(rels);
-
- return latestXid;
}
/*
/*
* Here is where we really truly commit.
*/
- (void) RecordTransactionCommit();
+ RecordTransactionCommit();
TRACE_POSTGRESQL_TRANSACTION_COMMIT(MyProc->lxid);
RecordKnownAssignedTransactionIds(max_xid);
/*
- * Mark the transaction committed in pg_clog. We use async commit
- * protocol during recovery to provide information on database
- * consistency for when users try to set hint bits. It is important
+ * Mark the transaction committed in pg_clog. Note that this is
+ * analogous to an asynchronous commit, as we haven't updated
+ * minRecoveryPoint to the commit record yet. It is important
* that we do not set hint bits until the minRecoveryPoint is past
* this commit record. This ensures that if we crash we don't see hint
* bits set on changes made by transactions that haven't yet
* recovered. It's unlikely but it's good to be safe.
*/
- TransactionIdAsyncCommitTree(xid, nsubxacts, sub_xids, lsn);
+ TransactionIdSetCommitting(xid, nsubxacts, sub_xids);
+ TransactionIdCommitTree(xid, nsubxacts, sub_xids, lsn);
/*
* Send any cache invalidations attached to the commit. We must