Skip to content

Commit 6301c3a

Browse files
committed
Avoid O(N^2) behavior when the standby process releases many locks.
When replaying a transaction that held many exclusive locks on the primary, a standby server's startup process would expend O(N^2) effort on manipulating the list of locks. This code was fine when written, but commit 1cff1b9 made repetitive list_delete_first() calls inefficient, as explained in its commit message. Fix by just iterating the list normally, and releasing storage only when done. (This'd be inadequate if we needed to recover from an error occurring partway through; but we don't.) Back-patch to v13 where 1cff1b9 came in. Nathan Bossart Discussion: https://postgr.es/m/CD2F0E7F-9822-45EC-A411-AE56F14DEA9F@amazon.com
1 parent acb2d7d commit 6301c3a

File tree

1 file changed

+6
-4
lines changed

1 file changed

+6
-4
lines changed

src/backend/storage/ipc/standby.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -986,9 +986,11 @@ StandbyAcquireAccessExclusiveLock(TransactionId xid, Oid dbOid, Oid relOid)
986986
static void
987987
StandbyReleaseLockList(List *locks)
988988
{
989-
while (locks)
989+
ListCell *lc;
990+
991+
foreach(lc, locks)
990992
{
991-
xl_standby_lock *lock = (xl_standby_lock *) linitial(locks);
993+
xl_standby_lock *lock = (xl_standby_lock *) lfirst(lc);
992994
LOCKTAG locktag;
993995

994996
elog(trace_recovery(DEBUG4),
@@ -1002,9 +1004,9 @@ StandbyReleaseLockList(List *locks)
10021004
lock->xid, lock->dbOid, lock->relOid);
10031005
Assert(false);
10041006
}
1005-
pfree(lock);
1006-
locks = list_delete_first(locks);
10071007
}
1008+
1009+
list_free_deep(locks);
10081010
}
10091011

10101012
static void

0 commit comments

Comments
 (0)