Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commited78384

Browse files
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 duringlock processing on standby.Bug report and diagnosis by Fujii Masao, fix by me.
1 parentc623365 commited78384

File tree

3 files changed

+43
-16
lines changed

3 files changed

+43
-16
lines changed

‎src/backend/storage/ipc/standby.c

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -953,14 +953,6 @@ LogAccessExclusiveLock(Oid dbOid, Oid relOid)
953953
{
954954
xl_standby_lockxlrec;
955955

956-
/*
957-
* Ensure that a TransactionId has been assigned to this transaction. We
958-
* don't actually need the xid yet but if we don't do this then
959-
* RecordTransactionCommit() and RecordTransactionAbort() will optimise
960-
* away the transaction completion record which recovery relies upon to
961-
* release locks. It's a hack, but for a corner case not worth adding code
962-
* for into the main commit path.
963-
*/
964956
xlrec.xid=GetTopTransactionId();
965957

966958
/*
@@ -973,3 +965,24 @@ LogAccessExclusiveLock(Oid dbOid, Oid relOid)
973965

974966
LogAccessExclusiveLocks(1,&xlrec);
975967
}
968+
969+
/*
970+
* Prepare to log an AccessExclusiveLock, for use during LockAcquire()
971+
*/
972+
void
973+
LogAccessExclusiveLockPrepare(void)
974+
{
975+
/*
976+
* Ensure that a TransactionId has been assigned to this transaction,
977+
* for two reasons, both related to lock release on the standby.
978+
* First, we must assign an xid so that RecordTransactionCommit() and
979+
* RecordTransactionAbort() do not optimise away the transaction
980+
* completion record which recovery relies upon to release locks. It's
981+
* a hack, but for a corner case not worth adding code for into the
982+
* main commit path. Second, must must assign an xid before the lock
983+
* is recorded in shared memory, otherwise a concurrently executing
984+
* GetRunningTransactionLocks() might see a lock associated with an
985+
* InvalidTransactionId which we later assert cannot happen.
986+
*/
987+
(void)GetTopTransactionId();
988+
}

‎src/backend/storage/lmgr/lock.c

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -499,6 +499,7 @@ LockAcquireExtended(const LOCKTAG *locktag,
499499
intpartition;
500500
LWLockIdpartitionLock;
501501
intstatus;
502+
boollog_lock= false;
502503

503504
if (lockmethodid <=0||lockmethodid >=lengthof(LockMethods))
504505
elog(ERROR,"unrecognized lock method: %d",lockmethodid);
@@ -579,6 +580,24 @@ LockAcquireExtended(const LOCKTAG *locktag,
579580
returnLOCKACQUIRE_ALREADY_HELD;
580581
}
581582

583+
/*
584+
* Emit a WAL record if acquisition of this lock needs to be replayed in a
585+
* standby server. Only AccessExclusiveLocks can conflict with lock types
586+
* that read-only transactions can acquire in a standby server.
587+
*
588+
* Make sure this definition matches the one in GetRunningTransactionLocks().
589+
*
590+
* First we prepare to log, then after lock acquired we issue log record.
591+
*/
592+
if (lockmode >=AccessExclusiveLock&&
593+
locktag->locktag_type==LOCKTAG_RELATION&&
594+
!RecoveryInProgress()&&
595+
XLogStandbyInfoActive())
596+
{
597+
LogAccessExclusiveLockPrepare();
598+
log_lock= true;
599+
}
600+
582601
/*
583602
* Otherwise we've got to mess with the shared lock table.
584603
*/
@@ -868,15 +887,9 @@ LockAcquireExtended(const LOCKTAG *locktag,
868887

869888
/*
870889
* Emit a WAL record if acquisition of this lock need to be replayed in a
871-
* standby server. Only AccessExclusiveLocks can conflict with lock types
872-
* that read-only transactions can acquire in a standby server.
873-
*
874-
* Make sure this definition matches the one GetRunningTransactionLocks().
890+
* standby server.
875891
*/
876-
if (lockmode >=AccessExclusiveLock&&
877-
locktag->locktag_type==LOCKTAG_RELATION&&
878-
!RecoveryInProgress()&&
879-
XLogStandbyInfoActive())
892+
if (log_lock)
880893
{
881894
/*
882895
* Decode the locktag back to the original values, to avoid sending

‎src/include/storage/standby.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ typedef struct RunningTransactionsData
109109
typedefRunningTransactionsData*RunningTransactions;
110110

111111
externvoidLogAccessExclusiveLock(OiddbOid,OidrelOid);
112+
externvoidLogAccessExclusiveLockPrepare(void);
112113

113114
externvoidLogStandbySnapshot(TransactionId*oldestActiveXid,TransactionId*nextXid);
114115

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp