diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/access/transam/xlog.c | 101 |
1 files changed, 58 insertions, 43 deletions
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index fcbde10529b..39aec70b625 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -792,59 +792,74 @@ XLogInsertRecord(XLogRecData *rdata, *---------- */ START_CRIT_SECTION(); - if (isLogSwitch) - WALInsertLockAcquireExclusive(); - else - WALInsertLockAcquire(); - /* - * Check to see if my copy of RedoRecPtr is out of date. If so, may have - * to go back and have the caller recompute everything. This can only - * happen just after a checkpoint, so it's better to be slow in this case - * and fast otherwise. - * - * Also check to see if fullPageWrites was just turned on or there's a - * running backup (which forces full-page writes); if we weren't already - * doing full-page writes then go back and recompute. - * - * If we aren't doing full-page writes then RedoRecPtr doesn't actually - * affect the contents of the XLOG record, so we'll update our local copy - * but not force a recomputation. (If doPageWrites was just turned off, - * we could recompute the record without full pages, but we choose not to - * bother.) - */ - if (RedoRecPtr != Insert->RedoRecPtr) + if (likely(!isLogSwitch)) { - Assert(RedoRecPtr < Insert->RedoRecPtr); - RedoRecPtr = Insert->RedoRecPtr; - } - doPageWrites = (Insert->fullPageWrites || Insert->runningBackups > 0); + WALInsertLockAcquire(); - if (doPageWrites && - (!prevDoPageWrites || - (fpw_lsn != InvalidXLogRecPtr && fpw_lsn <= RedoRecPtr))) - { /* - * Oops, some buffer now needs to be backed up that the caller didn't - * back up. Start over. + * Check to see if my copy of RedoRecPtr is out of date. If so, may + * have to go back and have the caller recompute everything. This can + * only happen just after a checkpoint, so it's better to be slow in + * this case and fast otherwise. + * + * Also check to see if fullPageWrites was just turned on or there's a + * running backup (which forces full-page writes); if we weren't + * already doing full-page writes then go back and recompute. + * + * If we aren't doing full-page writes then RedoRecPtr doesn't + * actually affect the contents of the XLOG record, so we'll update + * our local copy but not force a recomputation. (If doPageWrites was + * just turned off, we could recompute the record without full pages, + * but we choose not to bother.) */ - WALInsertLockRelease(); - END_CRIT_SECTION(); - return InvalidXLogRecPtr; - } + if (RedoRecPtr != Insert->RedoRecPtr) + { + Assert(RedoRecPtr < Insert->RedoRecPtr); + RedoRecPtr = Insert->RedoRecPtr; + } + doPageWrites = (Insert->fullPageWrites || Insert->runningBackups > 0); - /* - * Reserve space for the record in the WAL. This also sets the xl_prev - * pointer. - */ - if (isLogSwitch) - inserted = ReserveXLogSwitch(&StartPos, &EndPos, &rechdr->xl_prev); - else - { + if (doPageWrites && + (!prevDoPageWrites || + (fpw_lsn != InvalidXLogRecPtr && fpw_lsn <= RedoRecPtr))) + { + /* + * Oops, some buffer now needs to be backed up that the caller + * didn't back up. Start over. + */ + WALInsertLockRelease(); + END_CRIT_SECTION(); + return InvalidXLogRecPtr; + } + + /* + * Reserve space for the record in the WAL. This also sets the xl_prev + * pointer. + */ ReserveXLogInsertLocation(rechdr->xl_tot_len, &StartPos, &EndPos, &rechdr->xl_prev); + + /* Normal records are always inserted. */ inserted = true; } + else + { + /* + * In order to insert an XLOG_SWITCH record, we need to hold all of + * the WAL insertion locks, not just one, so that no one else can + * begin inserting a record until we've figured out how much space + * remains in the current WAL segment and claimed all of it. + * + * Nonetheless, this case is simpler than the normal cases handled + * above, which must check for changes in doPageWrites and RedoRecPtr. + * Those checks are only needed for records that can contain + * full-pages images, and an XLOG_SWITCH record never does. + */ + Assert(fpw_lsn == InvalidXLogRecPtr); + WALInsertLockAcquireExclusive(); + inserted = ReserveXLogSwitch(&StartPos, &EndPos, &rechdr->xl_prev); + } if (inserted) { |