diff options
Diffstat (limited to 'src/backend/access/transam/xlog.c')
-rw-r--r-- | src/backend/access/transam/xlog.c | 36 |
1 files changed, 29 insertions, 7 deletions
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index 4b273a8318f..cce87a3cd30 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -2118,23 +2118,43 @@ XLogFlush(XLogRecPtr record) /* initialize to given target; may increase below */ WriteRqstPtr = record; - /* read LogwrtResult and update local state */ + /* + * Now wait until we get the write lock, or someone else does the + * flush for us. + */ + for (;;) { /* use volatile pointer to prevent code rearrangement */ volatile XLogCtlData *xlogctl = XLogCtl; + /* read LogwrtResult and update local state */ SpinLockAcquire(&xlogctl->info_lck); if (XLByteLT(WriteRqstPtr, xlogctl->LogwrtRqst.Write)) WriteRqstPtr = xlogctl->LogwrtRqst.Write; LogwrtResult = xlogctl->LogwrtResult; SpinLockRelease(&xlogctl->info_lck); - } - /* done already? */ - if (!XLByteLE(record, LogwrtResult.Flush)) - { - /* now wait for the write lock */ - LWLockAcquire(WALWriteLock, LW_EXCLUSIVE); + /* done already? */ + if (XLByteLE(record, LogwrtResult.Flush)) + break; + + /* + * Try to get the write lock. If we can't get it immediately, wait + * until it's released, and recheck if we still need to do the flush + * or if the backend that held the lock did it for us already. This + * helps to maintain a good rate of group committing when the system + * is bottlenecked by the speed of fsyncing. + */ + if (!LWLockWaitUntilFree(WALWriteLock, LW_EXCLUSIVE)) + { + /* + * The lock is now free, but we didn't acquire it yet. Before we + * do, loop back to check if someone else flushed the record for + * us already. + */ + continue; + } + /* Got the lock */ LogwrtResult = XLogCtl->Write.LogwrtResult; if (!XLByteLE(record, LogwrtResult.Flush)) { @@ -2163,6 +2183,8 @@ XLogFlush(XLogRecPtr record) XLogWrite(WriteRqst, false, false); } LWLockRelease(WALWriteLock); + /* done */ + break; } END_CRIT_SECTION(); |