Patch to reduce WAL log space usage - Mailing list pgsql-patches
From | Tom Lane |
---|---|
Subject | Patch to reduce WAL log space usage |
Date | |
Msg-id | 3098.991848562@sss.pgh.pa.us Whole thread Raw |
List | pgsql-patches |
Per recent discussions in pghackers, I have tweaked the WAL code so that each checkpoint truncates the log at the prior checkpoint's redo point, not its undo point. (There is no point in keeping the undo information until we have UNDO support, which doesn't seem to be imminent.) This should reduce disk space usage very considerably in the presence of long-running transactions. Since I'm not sure if or how soon there will be a 7.1.3 release, I'm posting the patch here in case people want to apply it locally. Note: the diff also ensures that out-of-disk-space failures in WAL logfile creation will be reported correctly. regards, tom lane *** src/backend/access/transam/xlog.c~ Thu Apr 5 12:55:21 2001 --- src/backend/access/transam/xlog.c Wed Jun 6 13:14:38 2001 *************** *** 1068,1076 **** --- 1068,1082 ---- /* OK to write the page */ from = XLogCtl->pages + Write->curridx * BLCKSZ; + errno = 0; if (write(openLogFile, from, BLCKSZ) != BLCKSZ) + { + /* if write didn't set errno, assume problem is no disk space */ + if (errno == 0) + errno = ENOSPC; elog(STOP, "write(logfile %u seg %u off %u) failed: %m", openLogId, openLogSeg, openLogOff); + } openLogOff += BLCKSZ; /* *************** *** 1323,1328 **** --- 1329,1335 ---- MemSet(zbuffer, 0, sizeof(zbuffer)); for (nbytes = 0; nbytes < XLogSegSize; nbytes += sizeof(zbuffer)) { + errno = 0; if ((int) write(fd, zbuffer, sizeof(zbuffer)) != (int) sizeof(zbuffer)) { int save_errno = errno; *************** *** 1332,1338 **** * space */ unlink(tmppath); ! errno = save_errno; elog(STOP, "ZeroFill(%s) failed: %m", tmppath); } --- 1339,1346 ---- * space */ unlink(tmppath); ! /* if write didn't set errno, assume problem is no disk space */ ! errno = save_errno ? save_errno : ENOSPC; elog(STOP, "ZeroFill(%s) failed: %m", tmppath); } *************** *** 1987,1994 **** --- 1995,2008 ---- elog(STOP, "WriteControlFile failed to create control file (%s): %m", ControlFilePath); + errno = 0; if (write(fd, buffer, BLCKSZ) != BLCKSZ) + { + /* if write didn't set errno, assume problem is no disk space */ + if (errno == 0) + errno = ENOSPC; elog(STOP, "WriteControlFile failed to write control file: %m"); + } if (pg_fsync(fd) != 0) elog(STOP, "WriteControlFile failed to fsync control file: %m"); *************** *** 2085,2092 **** --- 2099,2112 ---- if (fd < 0) elog(STOP, "open(\"%s\") failed: %m", ControlFilePath); + errno = 0; if (write(fd, ControlFile, sizeof(ControlFileData)) != sizeof(ControlFileData)) + { + /* if write didn't set errno, assume problem is no disk space */ + if (errno == 0) + errno = ENOSPC; elog(STOP, "write(cntlfile) failed: %m"); + } if (pg_fsync(fd) != 0) elog(STOP, "fsync(cntlfile) failed: %m"); *************** *** 2224,2231 **** --- 2244,2257 ---- use_existent = false; openLogFile = XLogFileInit(0, 0, &use_existent, false); + errno = 0; if (write(openLogFile, buffer, BLCKSZ) != BLCKSZ) + { + /* if write didn't set errno, assume problem is no disk space */ + if (errno == 0) + errno = ENOSPC; elog(STOP, "BootStrapXLOG failed to write logfile: %m"); + } if (pg_fsync(openLogFile) != 0) elog(STOP, "BootStrapXLOG failed to fsync logfile: %m"); *************** *** 2816,2830 **** elog(STOP, "XLog concurrent activity while data base is shutting down"); /* ! * Remember location of prior checkpoint's earliest info. Oldest item ! * is redo or undo, whichever is older; but watch out for case that ! * undo = 0. */ if (ControlFile->checkPointCopy.undo.xrecoff != 0 && XLByteLT(ControlFile->checkPointCopy.undo, ControlFile->checkPointCopy.redo)) XLByteToSeg(ControlFile->checkPointCopy.undo, _logId, _logSeg); else XLByteToSeg(ControlFile->checkPointCopy.redo, _logId, _logSeg); /* --- 2842,2863 ---- elog(STOP, "XLog concurrent activity while data base is shutting down"); /* ! * Select point at which we can truncate the log, which we base on the ! * prior checkpoint's earliest info. ! * ! * With UNDO support: oldest item is redo or undo, whichever is older; ! * but watch out for case that undo = 0. ! * ! * Without UNDO support: just use the redo pointer. This allows xlog ! * space to be freed much faster when there are long-running transactions. */ + #ifdef NOT_USED if (ControlFile->checkPointCopy.undo.xrecoff != 0 && XLByteLT(ControlFile->checkPointCopy.undo, ControlFile->checkPointCopy.redo)) XLByteToSeg(ControlFile->checkPointCopy.undo, _logId, _logSeg); else + #endif XLByteToSeg(ControlFile->checkPointCopy.redo, _logId, _logSeg); /*
pgsql-patches by date: