summaryrefslogtreecommitdiff
path: root/src/backend/storage/ipc
diff options
context:
space:
mode:
authorSimon Riggs <simon@2ndQuadrant.com>2010-11-29 01:10:56 +0000
committerSimon Riggs <simon@2ndQuadrant.com>2010-11-29 01:10:56 +0000
commit09425f89e764beabbdd30cc877b3de96f5d3d2b9 (patch)
tree453f6b115f641e624c0262841d22736d80c281ef /src/backend/storage/ipc
parente6fa73e87a3f3aeb4694ad3d20a179fb76e12ce1 (diff)
Move call to GetTopTransactionId() earlier in LockAcquire(),
removing an infrequently occurring race condition in Hot Standby. An xid must be assigned before a lock appears in shared memory, rather than immediately after, else GetRunningTransactionLocks() may see InvalidTransactionId, causing assertion failures during lock processing on standby. Bug report and diagnosis by Fujii Masao, fix by me.
Diffstat (limited to 'src/backend/storage/ipc')
-rw-r--r--src/backend/storage/ipc/standby.c29
1 files changed, 21 insertions, 8 deletions
diff --git a/src/backend/storage/ipc/standby.c b/src/backend/storage/ipc/standby.c
index 154147e44c2..ca094a01b40 100644
--- a/src/backend/storage/ipc/standby.c
+++ b/src/backend/storage/ipc/standby.c
@@ -953,14 +953,6 @@ LogAccessExclusiveLock(Oid dbOid, Oid relOid)
{
xl_standby_lock xlrec;
- /*
- * Ensure that a TransactionId has been assigned to this transaction. We
- * don't actually need the xid yet but if we don't do this then
- * RecordTransactionCommit() and RecordTransactionAbort() will optimise
- * away the transaction completion record which recovery relies upon to
- * release locks. It's a hack, but for a corner case not worth adding code
- * for into the main commit path.
- */
xlrec.xid = GetTopTransactionId();
/*
@@ -973,3 +965,24 @@ LogAccessExclusiveLock(Oid dbOid, Oid relOid)
LogAccessExclusiveLocks(1, &xlrec);
}
+
+/*
+ * Prepare to log an AccessExclusiveLock, for use during LockAcquire()
+ */
+void
+LogAccessExclusiveLockPrepare(void)
+{
+ /*
+ * Ensure that a TransactionId has been assigned to this transaction,
+ * for two reasons, both related to lock release on the standby.
+ * First, we must assign an xid so that RecordTransactionCommit() and
+ * RecordTransactionAbort() do not optimise away the transaction
+ * completion record which recovery relies upon to release locks. It's
+ * a hack, but for a corner case not worth adding code for into the
+ * main commit path. Second, must must assign an xid before the lock
+ * is recorded in shared memory, otherwise a concurrently executing
+ * GetRunningTransactionLocks() might see a lock associated with an
+ * InvalidTransactionId which we later assert cannot happen.
+ */
+ (void) GetTopTransactionId();
+}