From: Andres Freund Date: Thu, 31 Dec 2020 04:04:10 +0000 (-0800) Subject: xlog: Use LWLockAcquireOrWait() in AdvanceXLInsertBuffer. X-Git-Url: http://git.postgresql.org/gitweb/static/gitweb.js?a=commitdiff_plain;h=559f13e6162b40b7c8327ed916e37e5437e567bc;p=users%2Fandresfreund%2Fpostgres.git xlog: Use LWLockAcquireOrWait() in AdvanceXLInsertBuffer. Otherwise a lot of backends may unnecessarily acquire the lock exclusively one-by-one. Author: Reviewed-By: Discussion: https://postgr.es/m/ Backpatch: --- diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index 56d1d29fbe..dec645c416 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -2284,14 +2284,33 @@ AdvanceXLInsertBuffer(XLogRecPtr upto, bool opportunistic) XLogPageHeader NewPage; int npages = 0; - LWLockAcquire(WALBufMappingLock, LW_EXCLUSIVE); +retry: + if (opportunistic) + { + if (!LWLockConditionalAcquire(WALBufMappingLock, LW_EXCLUSIVE)) + return; + } + else if (!LWLockAcquireOrWait(WALBufMappingLock, LW_EXCLUSIVE)) + { + if (upto < XLogCtl->InitializedUpTo) + return; + goto retry; + } /* * Now that we have the lock, check if someone initialized the page * already. */ - while (upto >= XLogCtl->InitializedUpTo || opportunistic) + while (true) { + if (!opportunistic && upto < XLogCtl->InitializedUpTo) + { + ereport(DEBUG3, errmsg("moving to opportunistic"), + errhidestmt(true), + errhidecontext(true)); + opportunistic = true; + } + nextidx = XLogRecPtrToBufIdx(XLogCtl->InitializedUpTo); /* @@ -2341,9 +2360,7 @@ AdvanceXLInsertBuffer(XLogRecPtr upto, bool opportunistic) pgWalUsage.wal_buffers_full++; TRACE_POSTGRESQL_WAL_BUFFER_WRITE_DIRTY_DONE(); - /* Re-acquire WALBufMappingLock and retry */ - LWLockAcquire(WALBufMappingLock, LW_EXCLUSIVE); - continue; + goto retry; } } @@ -2361,6 +2378,10 @@ AdvanceXLInsertBuffer(XLogRecPtr upto, bool opportunistic) /* * Be sure to re-zero the buffer so that bytes beyond what we've * written will look like zeroes and not valid XLOG records... + * + * FIXME: We should avoid doing this under the lock - that's pretty + * slow. It's also not helpful to cause unnecessary cacheline pingpong + * for the page(s) in concurrent workloads. */ MemSet((char *) NewPage, 0, XLOG_BLCKSZ);