diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/backend/storage/ipc/standby.c | 29 | ||||
| -rw-r--r-- | src/backend/storage/lmgr/lock.c | 29 | ||||
| -rw-r--r-- | src/include/storage/standby.h | 1 | 
3 files changed, 43 insertions, 16 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(); +} diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index b196174f6e1..f48193c8e73 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 diff --git a/src/include/storage/standby.h b/src/include/storage/standby.h index 0654c5bcccf..42fa0c04a17 100644 --- a/src/include/storage/standby.h +++ b/src/include/storage/standby.h @@ -109,6 +109,7 @@ typedef struct RunningTransactionsData  typedef RunningTransactionsData *RunningTransactions;  extern void LogAccessExclusiveLock(Oid dbOid, Oid relOid); +extern void LogAccessExclusiveLockPrepare(void);  extern void LogStandbySnapshot(TransactionId *oldestActiveXid, TransactionId *nextXid); | 
