xlog: Use LWLockAcquireOrWait() in AdvanceXLInsertBuffer.
authorAndres Freund <andres@anarazel.de>
Thu, 31 Dec 2020 04:04:10 +0000 (20:04 -0800)
committerAndres Freund <andres@anarazel.de>
Mon, 11 Jan 2021 23:09:15 +0000 (15:09 -0800)
Otherwise a lot of backends may unnecessarily acquire the lock
exclusively one-by-one.

Author:
Reviewed-By:
Discussion: https://postgr.es/m/
Backpatch:

src/backend/access/transam/xlog.c

index 56d1d29fbe6aed6ace0534dc5b4581d6792f4f91..dec645c4169d338e8aba96a2bc8dc1c4212d47d6 100644 (file)
@@ -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);