diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index 86debf4..ee118f6 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -2155,10 +2155,13 @@ XLogWrite(XLogwrtRqst WriteRqst, bool flexible) bool last_iteration; bool finishing_seg; bool use_existent; + bool first_write; int curridx; int npages; int startidx; uint32 startoffset; + uint32 startidx_offset; + XLogRecPtr startXLogPtr; /* We should always be inside a critical section here */ Assert(CritSectionCount > 0); @@ -2175,11 +2178,20 @@ XLogWrite(XLogwrtRqst WriteRqst, bool flexible) * written together; startidx is the cache block index of the first one, * and startoffset is the file offset at which it should go. The latter * two variables are only valid when npages > 0, but we must initialize - * all of them to keep the compiler quiet. + * all of them to keep the compiler quiet. startidx_offset is the offset + * of the cached block which indicates from where to start writing and + * startXLogPtr is used to calculate the startoffset for the first write. + * startidx_offset and startXLogPtr helps to calculate the starting position + * of write, we need to to start writing from the position where previous + * write has finished instead of starting from page boundary as that can + * avoid re-writing WAL data. */ npages = 0; startidx = 0; startoffset = 0; + startidx_offset = 0; + startXLogPtr = LogwrtResult.Write; + first_write = true; /* * Within the loop, curridx is the cache block index of the page to @@ -2237,7 +2249,21 @@ XLogWrite(XLogwrtRqst WriteRqst, bool flexible) { /* first of group */ startidx = curridx; - startoffset = (LogwrtResult.Write - XLOG_BLCKSZ) % XLogSegSize; + startidx_offset = 0; + + /* + * for first page, we might need to start writing from somewhere + * in-between the page. + */ + if (first_write) + { + startidx_offset = startXLogPtr % XLOG_BLCKSZ; + startoffset = startXLogPtr % XLogSegSize; + } + else + startoffset = (LogwrtResult.Write - XLOG_BLCKSZ) % XLogSegSize; + + first_write = false; } npages++; @@ -2274,8 +2300,28 @@ XLogWrite(XLogwrtRqst WriteRqst, bool flexible) } /* OK to write the page(s) */ - from = XLogCtl->pages + startidx * (Size) XLOG_BLCKSZ; - nbytes = npages * (Size) XLOG_BLCKSZ; + from = XLogCtl->pages + startidx * (Size) XLOG_BLCKSZ + startidx_offset; + + /* + * write till the WriteRqst instead of till page boundary, this + * helps to avoid extra wal writes. + */ + if (last_iteration) + { + if (npages > 1) + { + nbytes = (npages - 1) * (Size) XLOG_BLCKSZ - startidx_offset; + nbytes += (((uint32) WriteRqst.Write) % XLOG_BLCKSZ == 0) ? + XLOG_BLCKSZ : ((uint32) WriteRqst.Write) % XLOG_BLCKSZ; + } + else + nbytes = (((uint32) WriteRqst.Write) % XLOG_BLCKSZ == 0) ? + XLOG_BLCKSZ - startidx_offset : ((uint32) WriteRqst.Write) % XLOG_BLCKSZ - + startidx_offset; + } + else + nbytes = npages * (Size) XLOG_BLCKSZ - startidx_offset; + nleft = nbytes; do { @@ -2288,9 +2334,9 @@ XLogWrite(XLogwrtRqst WriteRqst, bool flexible) ereport(PANIC, (errcode_for_file_access(), errmsg("could not write to log file %s " - "at offset %u, length %zu: %m", + "at offset %u, length %zu, last_iter %d, num_pages %d: %m", XLogFileNameP(ThisTimeLineID, openLogSegNo), - openLogOff, nbytes))); + openLogOff, nbytes, last_iteration, npages))); } nleft -= written; from += written;