mirror of
https://github.com/postgres/postgres.git
synced 2025-04-25 21:42:33 +03:00
Remove AELs from subxids correctly on standby
Issues relate only to subtransactions that hold AccessExclusiveLocks when replayed on standby. Prior to PG10, aborting subtransactions that held an AccessExclusiveLock failed to release the lock until top level commit or abort. 49bff5300d527 fixed that. However, 49bff5300d527 also introduced a similar bug where subtransaction commit would fail to release an AccessExclusiveLock, leaving the lock to be removed sometimes early and sometimes late. This commit fixes that bug also. Backpatch to PG10 needed. Tested by observation. Note need for multi-node isolationtester to improve test coverage for this and other HS cases. Reported-by: Simon Riggs Author: Simon Riggs
This commit is contained in:
parent
1cfdb1cb0e
commit
15378c1a15
@ -5602,12 +5602,10 @@ xact_redo_commit(xl_xact_parsed_commit *parsed,
|
|||||||
/*
|
/*
|
||||||
* Release locks, if any. We do this for both two phase and normal one
|
* Release locks, if any. We do this for both two phase and normal one
|
||||||
* phase transactions. In effect we are ignoring the prepare phase and
|
* phase transactions. In effect we are ignoring the prepare phase and
|
||||||
* just going straight to lock release. At commit we release all locks
|
* just going straight to lock release.
|
||||||
* via their top-level xid only, so no need to provide subxact list,
|
|
||||||
* which will save time when replaying commits.
|
|
||||||
*/
|
*/
|
||||||
if (parsed->xinfo & XACT_XINFO_HAS_AE_LOCKS)
|
if (parsed->xinfo & XACT_XINFO_HAS_AE_LOCKS)
|
||||||
StandbyReleaseLockTree(xid, 0, NULL);
|
StandbyReleaseLockTree(xid, parsed->nsubxacts, parsed->subxacts);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parsed->xinfo & XACT_XINFO_HAS_ORIGIN)
|
if (parsed->xinfo & XACT_XINFO_HAS_ORIGIN)
|
||||||
|
@ -684,11 +684,8 @@ ProcArrayApplyRecoveryInfo(RunningTransactions running)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Remove stale locks, if any.
|
* Remove stale locks, if any.
|
||||||
*
|
|
||||||
* Locks are always assigned to the toplevel xid so we don't need to care
|
|
||||||
* about subxcnt/subxids (and by extension not about ->suboverflowed).
|
|
||||||
*/
|
*/
|
||||||
StandbyReleaseOldLocks(running->xcnt, running->xids);
|
StandbyReleaseOldLocks(running->oldestRunningXid);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If our snapshot is already valid, nothing else to do...
|
* If our snapshot is already valid, nothing else to do...
|
||||||
|
@ -722,7 +722,7 @@ StandbyReleaseAllLocks(void)
|
|||||||
* as long as they're not prepared transactions.
|
* as long as they're not prepared transactions.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
StandbyReleaseOldLocks(int nxids, TransactionId *xids)
|
StandbyReleaseOldLocks(TransactionId oldxid)
|
||||||
{
|
{
|
||||||
ListCell *cell,
|
ListCell *cell,
|
||||||
*prev,
|
*prev,
|
||||||
@ -741,26 +741,8 @@ StandbyReleaseOldLocks(int nxids, TransactionId *xids)
|
|||||||
|
|
||||||
if (StandbyTransactionIdIsPrepared(lock->xid))
|
if (StandbyTransactionIdIsPrepared(lock->xid))
|
||||||
remove = false;
|
remove = false;
|
||||||
else
|
else if (TransactionIdPrecedes(lock->xid, oldxid))
|
||||||
{
|
remove = true;
|
||||||
int i;
|
|
||||||
bool found = false;
|
|
||||||
|
|
||||||
for (i = 0; i < nxids; i++)
|
|
||||||
{
|
|
||||||
if (lock->xid == xids[i])
|
|
||||||
{
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If its not a running transaction, remove it.
|
|
||||||
*/
|
|
||||||
if (!found)
|
|
||||||
remove = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (remove)
|
if (remove)
|
||||||
{
|
{
|
||||||
|
@ -50,7 +50,7 @@ extern void StandbyAcquireAccessExclusiveLock(TransactionId xid, Oid dbOid, Oid
|
|||||||
extern void StandbyReleaseLockTree(TransactionId xid,
|
extern void StandbyReleaseLockTree(TransactionId xid,
|
||||||
int nsubxids, TransactionId *subxids);
|
int nsubxids, TransactionId *subxids);
|
||||||
extern void StandbyReleaseAllLocks(void);
|
extern void StandbyReleaseAllLocks(void);
|
||||||
extern void StandbyReleaseOldLocks(int nxids, TransactionId *xids);
|
extern void StandbyReleaseOldLocks(TransactionId oldxid);
|
||||||
|
|
||||||
#define MinSizeOfXactRunningXacts offsetof(xl_running_xacts, xids)
|
#define MinSizeOfXactRunningXacts offsetof(xl_running_xacts, xids)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user