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

Commit8572cc4

Browse files
Resolve timing issue with logging locks for Hot Standby.
We log AccessExclusiveLocks for replay onto standby nodes,but because of timing issues on ProcArray it is possible tolog a lock that is still held by a just committed transactionthat is very soon to be removed. To avoid any timing issue weavoid applying locks made by transactions with InvalidXid.Simon Riggs, bug report Tom Lane, diagnosis Pavan Deolasee
1 parentb896e1e commit8572cc4

File tree

4 files changed

+88
-44
lines changed

4 files changed

+88
-44
lines changed

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

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -466,7 +466,7 @@ ProcArrayApplyRecoveryInfo(RunningTransactions running)
466466
* Remove stale transactions, if any.
467467
*/
468468
ExpireOldKnownAssignedTransactionIds(running->oldestRunningXid);
469-
StandbyReleaseOldLocks(running->oldestRunningXid);
469+
StandbyReleaseOldLocks(running->xcnt,running->xids);
470470

471471
/*
472472
* If our snapshot is already valid, nothing else to do...
@@ -520,12 +520,6 @@ ProcArrayApplyRecoveryInfo(RunningTransactions running)
520520
* OK, we need to initialise from the RunningTransactionsData record
521521
*/
522522

523-
/*
524-
* Release any locks belonging to old transactions that are not running
525-
* according to the running-xacts record.
526-
*/
527-
StandbyReleaseOldLocks(running->nextXid);
528-
529523
/*
530524
* Nobody else is running yet, but take locks anyhow
531525
*/

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

Lines changed: 75 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -524,7 +524,9 @@ StandbyAcquireAccessExclusiveLock(TransactionId xid, Oid dbOid, Oid relOid)
524524
LOCKTAGlocktag;
525525

526526
/* Already processed? */
527-
if (TransactionIdDidCommit(xid)||TransactionIdDidAbort(xid))
527+
if (!TransactionIdIsValid(xid)||
528+
TransactionIdDidCommit(xid)||
529+
TransactionIdDidAbort(xid))
528530
return;
529531

530532
elog(trace_recovery(DEBUG4),
@@ -606,34 +608,86 @@ StandbyReleaseLockTree(TransactionId xid, int nsubxids, TransactionId *subxids)
606608
}
607609

608610
/*
609-
* StandbyReleaseLocksMany
610-
*Release standby locks held by XIDs < removeXid
611-
*
612-
* If keepPreparedXacts is true, keep prepared transactions even if
613-
* they're older than removeXid
611+
* Called at end of recovery and when we see a shutdown checkpoint.
614612
*/
615-
staticvoid
616-
StandbyReleaseLocksMany(TransactionIdremoveXid,boolkeepPreparedXacts)
613+
void
614+
StandbyReleaseAllLocks(void)
615+
{
616+
ListCell*cell,
617+
*prev,
618+
*next;
619+
LOCKTAGlocktag;
620+
621+
elog(trace_recovery(DEBUG2),"release all standby locks");
622+
623+
prev=NULL;
624+
for (cell=list_head(RecoveryLockList);cell;cell=next)
625+
{
626+
xl_standby_lock*lock= (xl_standby_lock*)lfirst(cell);
627+
628+
next=lnext(cell);
629+
630+
elog(trace_recovery(DEBUG4),
631+
"releasing recovery lock: xid %u db %u rel %u",
632+
lock->xid,lock->dbOid,lock->relOid);
633+
SET_LOCKTAG_RELATION(locktag,lock->dbOid,lock->relOid);
634+
if (!LockRelease(&locktag,AccessExclusiveLock, true))
635+
elog(LOG,
636+
"RecoveryLockList contains entry for lock no longer recorded by lock manager: xid %u database %u relation %u",
637+
lock->xid,lock->dbOid,lock->relOid);
638+
RecoveryLockList=list_delete_cell(RecoveryLockList,cell,prev);
639+
pfree(lock);
640+
}
641+
}
642+
643+
/*
644+
* StandbyReleaseOldLocks
645+
*Release standby locks held by XIDs that aren't running, as long
646+
*as they're not prepared transactions.
647+
*/
648+
void
649+
StandbyReleaseOldLocks(intnxids,TransactionId*xids)
617650
{
618651
ListCell*cell,
619652
*prev,
620653
*next;
621654
LOCKTAGlocktag;
622655

623-
/*
624-
* Release all matching locks.
625-
*/
626656
prev=NULL;
627657
for (cell=list_head(RecoveryLockList);cell;cell=next)
628658
{
629659
xl_standby_lock*lock= (xl_standby_lock*)lfirst(cell);
660+
boolremove= false;
630661

631662
next=lnext(cell);
632663

633-
if (!TransactionIdIsValid(removeXid)||TransactionIdPrecedes(lock->xid,removeXid))
664+
Assert(TransactionIdIsValid(lock->xid));
665+
666+
if (StandbyTransactionIdIsPrepared(lock->xid))
667+
remove= false;
668+
else
669+
{
670+
inti;
671+
boolfound= false;
672+
673+
for (i=0;i<nxids;i++)
674+
{
675+
if (lock->xid==xids[i])
676+
{
677+
found= true;
678+
break;
679+
}
680+
}
681+
682+
/*
683+
* If its not a running transaction, remove it.
684+
*/
685+
if (!found)
686+
remove= true;
687+
}
688+
689+
if (remove)
634690
{
635-
if (keepPreparedXacts&&StandbyTransactionIdIsPrepared(lock->xid))
636-
continue;
637691
elog(trace_recovery(DEBUG4),
638692
"releasing recovery lock: xid %u db %u rel %u",
639693
lock->xid,lock->dbOid,lock->relOid);
@@ -650,27 +704,6 @@ StandbyReleaseLocksMany(TransactionId removeXid, bool keepPreparedXacts)
650704
}
651705
}
652706

653-
/*
654-
* Called at end of recovery and when we see a shutdown checkpoint.
655-
*/
656-
void
657-
StandbyReleaseAllLocks(void)
658-
{
659-
elog(trace_recovery(DEBUG2),"release all standby locks");
660-
StandbyReleaseLocksMany(InvalidTransactionId, false);
661-
}
662-
663-
/*
664-
* StandbyReleaseOldLocks
665-
*Release standby locks held by XIDs < removeXid, as long
666-
*as they're not prepared transactions.
667-
*/
668-
void
669-
StandbyReleaseOldLocks(TransactionIdremoveXid)
670-
{
671-
StandbyReleaseLocksMany(removeXid, true);
672-
}
673-
674707
/*
675708
* --------------------------------------------------------------------
676709
*Recovery handling for Rmgr RM_STANDBY_ID
@@ -812,6 +845,13 @@ standby_desc(StringInfo buf, uint8 xl_info, char *rec)
812845
* Later, when we apply the running xact data we must be careful to ignore
813846
* transactions already committed, since those commits raced ahead when
814847
* making WAL entries.
848+
*
849+
* The loose timing also means that locks may be recorded that have a
850+
* zero xid, since xids are removed from procs before locks are removed.
851+
* So we must prune the lock list down to ensure we hold locks only for
852+
* currently running xids, performed by StandbyReleaseOldLocks().
853+
* Zero xids should no longer be possible, but we may be replaying WAL
854+
* from a time when they were possible.
815855
*/
816856
void
817857
LogStandbySnapshot(TransactionId*nextXid)

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

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2355,8 +2355,18 @@ GetRunningTransactionLocks(int *nlocks)
23552355
{
23562356
PGPROC*proc=proclock->tag.myProc;
23572357
LOCK*lock=proclock->tag.myLock;
2358+
TransactionIdxid=proc->xid;
23582359

2359-
accessExclusiveLocks[index].xid=proc->xid;
2360+
/*
2361+
* Don't record locks for transactions if we know they have already
2362+
* issued their WAL record for commit but not yet released lock.
2363+
* It is still possible that we see locks held by already complete
2364+
* transactions, if they haven't yet zeroed their xids.
2365+
*/
2366+
if (!TransactionIdIsValid(xid))
2367+
continue;
2368+
2369+
accessExclusiveLocks[index].xid=xid;
23602370
accessExclusiveLocks[index].dbOid=lock->tag.locktag_field1;
23612371
accessExclusiveLocks[index].relOid=lock->tag.locktag_field2;
23622372

‎src/include/storage/standby.h‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ extern void StandbyAcquireAccessExclusiveLock(TransactionId xid, Oid dbOid, Oid
4848
externvoidStandbyReleaseLockTree(TransactionIdxid,
4949
intnsubxids,TransactionId*subxids);
5050
externvoidStandbyReleaseAllLocks(void);
51-
externvoidStandbyReleaseOldLocks(TransactionIdremoveXid);
51+
externvoidStandbyReleaseOldLocks(intnxids,TransactionId*xids);
5252

5353
/*
5454
* XLOG message types

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp