diff options
author | Simon Riggs <simon@2ndQuadrant.com> | 2010-11-29 01:08:02 +0000 |
---|---|---|
committer | Simon Riggs <simon@2ndQuadrant.com> | 2010-11-29 01:08:02 +0000 |
commit | ed78384acd691e3336e170aa18af69d15d088027 (patch) | |
tree | 1e7e4ccbe186c90546ebf3817f60b996780dc405 /src/backend/storage/lmgr/lock.c | |
parent | c623365ff9a5ef937e05b85c2feb5a5c5cde9b3b (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/lmgr/lock.c')
-rw-r--r-- | src/backend/storage/lmgr/lock.c | 29 |
1 files changed, 21 insertions, 8 deletions
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 45cfbc07102..e7cf1cd7ad0 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -499,6 +499,7 @@ LockAcquireExtended(const LOCKTAG *locktag, int partition; LWLockId partitionLock; int status; + bool log_lock = false; if (lockmethodid <= 0 || lockmethodid >= lengthof(LockMethods)) elog(ERROR, "unrecognized lock method: %d", lockmethodid); @@ -580,6 +581,24 @@ LockAcquireExtended(const LOCKTAG *locktag, } /* + * Emit a WAL record if acquisition of this lock needs to be replayed in a + * standby server. Only AccessExclusiveLocks can conflict with lock types + * that read-only transactions can acquire in a standby server. + * + * Make sure this definition matches the one in GetRunningTransactionLocks(). + * + * First we prepare to log, then after lock acquired we issue log record. + */ + if (lockmode >= AccessExclusiveLock && + locktag->locktag_type == LOCKTAG_RELATION && + !RecoveryInProgress() && + XLogStandbyInfoActive()) + { + LogAccessExclusiveLockPrepare(); + log_lock = true; + } + + /* * Otherwise we've got to mess with the shared lock table. */ hashcode = locallock->hashcode; @@ -868,15 +887,9 @@ LockAcquireExtended(const LOCKTAG *locktag, /* * Emit a WAL record if acquisition of this lock need to be replayed in a - * standby server. Only AccessExclusiveLocks can conflict with lock types - * that read-only transactions can acquire in a standby server. - * - * Make sure this definition matches the one GetRunningTransactionLocks(). + * standby server. */ - if (lockmode >= AccessExclusiveLock && - locktag->locktag_type == LOCKTAG_RELATION && - !RecoveryInProgress() && - XLogStandbyInfoActive()) + if (log_lock) { /* * Decode the locktag back to the original values, to avoid sending |