Adjust WAL code so that checkpoints truncate the xlog at the previous
checkpoint's redo pointer, not its undo pointer, per discussion in pghackers a few days ago. No point in hanging onto undo information until we have the ability to do something with it --- and this solves a rather large problem with log space for long-running transactions. Also, change all calls of write() to detect the case where write returned a count less than requested, but failed to set errno. Presume that this situation indicates ENOSPC, and give the appropriate error message, rather than a random message associated with the previous value of errno.
This commit is contained in:
parent
ce370eec35
commit
1173344e74
contrib
src/backend
@ -155,9 +155,8 @@ int dbf_write_head(dbhead *dbh) {
|
|||||||
put_short(head.dbh_hlen, dbh->db_hlen);
|
put_short(head.dbh_hlen, dbh->db_hlen);
|
||||||
put_short(head.dbh_rlen, dbh->db_rlen);
|
put_short(head.dbh_rlen, dbh->db_rlen);
|
||||||
|
|
||||||
if (write(dbh->db_fd, &head, sizeof(dbf_header)) == -1 ) {
|
if (write(dbh->db_fd, &head, sizeof(dbf_header)) != sizeof(dbf_header))
|
||||||
return DBF_ERROR;
|
return DBF_ERROR;
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -180,14 +179,12 @@ int dbf_put_fields(dbhead *dbh) {
|
|||||||
field.dbf_flen = dbh->db_fields[t].db_flen;
|
field.dbf_flen = dbh->db_fields[t].db_flen;
|
||||||
field.dbf_dec = dbh->db_fields[t].db_dec;
|
field.dbf_dec = dbh->db_fields[t].db_dec;
|
||||||
|
|
||||||
if (write(dbh->db_fd, &field, sizeof(dbf_field)) == -1) {
|
if (write(dbh->db_fd, &field, sizeof(dbf_field)) != sizeof(dbf_field))
|
||||||
return DBF_ERROR;
|
return DBF_ERROR;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (write(dbh->db_fd, &end, 1) == -1) {
|
if (write(dbh->db_fd, &end, 1) != 1)
|
||||||
return DBF_ERROR;
|
return DBF_ERROR;
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -457,15 +454,13 @@ int dbf_put_record(dbhead *dbh, field *rec, u_long where) {
|
|||||||
idx += rec[t].db_flen;
|
idx += rec[t].db_flen;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (write(dbh->db_fd, data, dbh->db_rlen) == -1) {
|
if (write(dbh->db_fd, data, dbh->db_rlen) != dbh->db_rlen)
|
||||||
return DBF_ERROR;
|
return DBF_ERROR;
|
||||||
}
|
|
||||||
|
|
||||||
/* There's a 0x1A at the end of a dbf-file */
|
/* There's a 0x1A at the end of a dbf-file */
|
||||||
if (where == dbh->db_records) {
|
if (where == dbh->db_records) {
|
||||||
if (write(dbh->db_fd, &end, 1) == -1) {
|
if (write(dbh->db_fd, &end, 1) != 1)
|
||||||
return DBF_ERROR;
|
return DBF_ERROR;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dbh->db_offset += dbh->db_rlen;
|
dbh->db_offset += dbh->db_rlen;
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Header: /cvsroot/pgsql/contrib/pg_resetxlog/Attic/pg_resetxlog.c,v 1.4 2001/05/30 14:18:18 momjian Exp $
|
* $Header: /cvsroot/pgsql/contrib/pg_resetxlog/Attic/pg_resetxlog.c,v 1.5 2001/06/06 17:07:38 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -772,8 +772,12 @@ RewriteControlFile(void)
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
if (write(fd, buffer, BLCKSZ) != BLCKSZ)
|
if (write(fd, buffer, BLCKSZ) != BLCKSZ)
|
||||||
{
|
{
|
||||||
|
/* if write didn't set errno, assume problem is no disk space */
|
||||||
|
if (errno == 0)
|
||||||
|
errno = ENOSPC;
|
||||||
perror("RewriteControlFile failed to write pg_control file");
|
perror("RewriteControlFile failed to write pg_control file");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
@ -884,8 +888,12 @@ WriteEmptyXLOG(void)
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
if (write(fd, buffer, BLCKSZ) != BLCKSZ)
|
if (write(fd, buffer, BLCKSZ) != BLCKSZ)
|
||||||
{
|
{
|
||||||
|
/* if write didn't set errno, assume problem is no disk space */
|
||||||
|
if (errno == 0)
|
||||||
|
errno = ENOSPC;
|
||||||
perror("WriteEmptyXLOG: failed to write xlog file");
|
perror("WriteEmptyXLOG: failed to write xlog file");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
@ -894,8 +902,11 @@ WriteEmptyXLOG(void)
|
|||||||
memset(buffer, 0, BLCKSZ);
|
memset(buffer, 0, BLCKSZ);
|
||||||
for (nbytes = BLCKSZ; nbytes < XLogSegSize; nbytes += BLCKSZ)
|
for (nbytes = BLCKSZ; nbytes < XLogSegSize; nbytes += BLCKSZ)
|
||||||
{
|
{
|
||||||
|
errno = 0;
|
||||||
if (write(fd, buffer, BLCKSZ) != BLCKSZ)
|
if (write(fd, buffer, BLCKSZ) != BLCKSZ)
|
||||||
{
|
{
|
||||||
|
if (errno == 0)
|
||||||
|
errno = ENOSPC;
|
||||||
perror("WriteEmptyXLOG: failed to write xlog file");
|
perror("WriteEmptyXLOG: failed to write xlog file");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Header: /cvsroot/pgsql/src/backend/access/transam/xlog.c,v 1.68 2001/06/03 14:53:56 petere Exp $
|
* $Header: /cvsroot/pgsql/src/backend/access/transam/xlog.c,v 1.69 2001/06/06 17:07:38 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -1068,9 +1068,15 @@ XLogWrite(XLogwrtRqst WriteRqst)
|
|||||||
|
|
||||||
/* OK to write the page */
|
/* OK to write the page */
|
||||||
from = XLogCtl->pages + Write->curridx * BLCKSZ;
|
from = XLogCtl->pages + Write->curridx * BLCKSZ;
|
||||||
|
errno = 0;
|
||||||
if (write(openLogFile, from, BLCKSZ) != BLCKSZ)
|
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 of log file %u, segment %u, offset %u failed: %m",
|
elog(STOP, "write of log file %u, segment %u, offset %u failed: %m",
|
||||||
openLogId, openLogSeg, openLogOff);
|
openLogId, openLogSeg, openLogOff);
|
||||||
|
}
|
||||||
openLogOff += BLCKSZ;
|
openLogOff += BLCKSZ;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1323,6 +1329,7 @@ XLogFileInit(uint32 log, uint32 seg,
|
|||||||
MemSet(zbuffer, 0, sizeof(zbuffer));
|
MemSet(zbuffer, 0, sizeof(zbuffer));
|
||||||
for (nbytes = 0; nbytes < XLogSegSize; nbytes += sizeof(zbuffer))
|
for (nbytes = 0; nbytes < XLogSegSize; nbytes += sizeof(zbuffer))
|
||||||
{
|
{
|
||||||
|
errno = 0;
|
||||||
if ((int) write(fd, zbuffer, sizeof(zbuffer)) != (int) sizeof(zbuffer))
|
if ((int) write(fd, zbuffer, sizeof(zbuffer)) != (int) sizeof(zbuffer))
|
||||||
{
|
{
|
||||||
int save_errno = errno;
|
int save_errno = errno;
|
||||||
@ -1332,7 +1339,8 @@ XLogFileInit(uint32 log, uint32 seg,
|
|||||||
* space
|
* space
|
||||||
*/
|
*/
|
||||||
unlink(tmppath);
|
unlink(tmppath);
|
||||||
errno = save_errno;
|
/* if write didn't set errno, assume problem is no disk space */
|
||||||
|
errno = save_errno ? save_errno : ENOSPC;
|
||||||
|
|
||||||
elog(STOP, "ZeroFill failed to create or write %s: %m", tmppath);
|
elog(STOP, "ZeroFill failed to create or write %s: %m", tmppath);
|
||||||
}
|
}
|
||||||
@ -1990,8 +1998,14 @@ WriteControlFile(void)
|
|||||||
elog(STOP, "WriteControlFile: could not create control file (%s): %m",
|
elog(STOP, "WriteControlFile: could not create control file (%s): %m",
|
||||||
ControlFilePath);
|
ControlFilePath);
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
if (write(fd, buffer, BLCKSZ) != BLCKSZ)
|
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: write to control file failed: %m");
|
elog(STOP, "WriteControlFile: write to control file failed: %m");
|
||||||
|
}
|
||||||
|
|
||||||
if (pg_fsync(fd) != 0)
|
if (pg_fsync(fd) != 0)
|
||||||
elog(STOP, "WriteControlFile: fsync of control file failed: %m");
|
elog(STOP, "WriteControlFile: fsync of control file failed: %m");
|
||||||
@ -2109,8 +2123,14 @@ UpdateControlFile(void)
|
|||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
elog(STOP, "could not open control file (%s): %m", ControlFilePath);
|
elog(STOP, "could not open control file (%s): %m", ControlFilePath);
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
if (write(fd, ControlFile, sizeof(ControlFileData)) != sizeof(ControlFileData))
|
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 to control file failed: %m");
|
elog(STOP, "write to control file failed: %m");
|
||||||
|
}
|
||||||
|
|
||||||
if (pg_fsync(fd) != 0)
|
if (pg_fsync(fd) != 0)
|
||||||
elog(STOP, "fsync of control file failed: %m");
|
elog(STOP, "fsync of control file failed: %m");
|
||||||
@ -2248,8 +2268,14 @@ BootStrapXLOG(void)
|
|||||||
use_existent = false;
|
use_existent = false;
|
||||||
openLogFile = XLogFileInit(0, 0, &use_existent, false);
|
openLogFile = XLogFileInit(0, 0, &use_existent, false);
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
if (write(openLogFile, buffer, BLCKSZ) != BLCKSZ)
|
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 log file: %m");
|
elog(STOP, "BootStrapXLOG failed to write log file: %m");
|
||||||
|
}
|
||||||
|
|
||||||
if (pg_fsync(openLogFile) != 0)
|
if (pg_fsync(openLogFile) != 0)
|
||||||
elog(STOP, "BootStrapXLOG failed to fsync log file: %m");
|
elog(STOP, "BootStrapXLOG failed to fsync log file: %m");
|
||||||
@ -2852,15 +2878,22 @@ CreateCheckPoint(bool shutdown)
|
|||||||
elog(STOP, "concurrent transaction log activity while database system is shutting down");
|
elog(STOP, "concurrent transaction log activity while database system is shutting down");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Remember location of prior checkpoint's earliest info. Oldest item
|
* Select point at which we can truncate the log, which we base on the
|
||||||
* is redo or undo, whichever is older; but watch out for case that
|
* prior checkpoint's earliest info.
|
||||||
* undo = 0.
|
*
|
||||||
|
* 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 &&
|
if (ControlFile->checkPointCopy.undo.xrecoff != 0 &&
|
||||||
XLByteLT(ControlFile->checkPointCopy.undo,
|
XLByteLT(ControlFile->checkPointCopy.undo,
|
||||||
ControlFile->checkPointCopy.redo))
|
ControlFile->checkPointCopy.redo))
|
||||||
XLByteToSeg(ControlFile->checkPointCopy.undo, _logId, _logSeg);
|
XLByteToSeg(ControlFile->checkPointCopy.undo, _logId, _logSeg);
|
||||||
else
|
else
|
||||||
|
#endif
|
||||||
XLByteToSeg(ControlFile->checkPointCopy.redo, _logId, _logSeg);
|
XLByteToSeg(ControlFile->checkPointCopy.redo, _logId, _logSeg);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/storage/file/fd.c,v 1.79 2001/05/30 14:15:26 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/storage/file/fd.c,v 1.80 2001/06/06 17:07:46 tgl Exp $
|
||||||
*
|
*
|
||||||
* NOTES:
|
* NOTES:
|
||||||
*
|
*
|
||||||
@ -865,7 +865,14 @@ FileWrite(File file, char *buffer, int amount)
|
|||||||
VfdCache[file].seekPos, amount, buffer));
|
VfdCache[file].seekPos, amount, buffer));
|
||||||
|
|
||||||
FileAccess(file);
|
FileAccess(file);
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
returnCode = write(VfdCache[file].fd, buffer, amount);
|
returnCode = write(VfdCache[file].fd, buffer, amount);
|
||||||
|
|
||||||
|
/* if write didn't set errno, assume problem is no disk space */
|
||||||
|
if (returnCode != amount && errno == 0)
|
||||||
|
errno = ENOSPC;
|
||||||
|
|
||||||
if (returnCode > 0)
|
if (returnCode > 0)
|
||||||
VfdCache[file].seekPos += returnCode;
|
VfdCache[file].seekPos += returnCode;
|
||||||
else
|
else
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/storage/smgr/md.c,v 1.84 2001/05/10 20:38:49 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/storage/smgr/md.c,v 1.85 2001/06/06 17:07:46 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -582,8 +582,12 @@ mdblindwrt(RelFileNode rnode,
|
|||||||
status = SM_SUCCESS;
|
status = SM_SUCCESS;
|
||||||
|
|
||||||
/* write and optionally sync the block */
|
/* write and optionally sync the block */
|
||||||
|
errno = 0;
|
||||||
if (write(fd, buffer, BLCKSZ) != BLCKSZ)
|
if (write(fd, buffer, BLCKSZ) != BLCKSZ)
|
||||||
{
|
{
|
||||||
|
/* if write didn't set errno, assume problem is no disk space */
|
||||||
|
if (errno == 0)
|
||||||
|
errno = ENOSPC;
|
||||||
elog(DEBUG, "mdblindwrt: write() failed: %m");
|
elog(DEBUG, "mdblindwrt: write() failed: %m");
|
||||||
status = SM_FAIL;
|
status = SM_FAIL;
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/utils/init/miscinit.c,v 1.68 2001/06/01 20:27:41 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/utils/init/miscinit.c,v 1.69 2001/06/06 17:07:46 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -659,13 +659,15 @@ CreateLockFile(const char *filename, bool amPostmaster,
|
|||||||
snprintf(buffer, sizeof(buffer), "%d\n%s\n",
|
snprintf(buffer, sizeof(buffer), "%d\n%s\n",
|
||||||
amPostmaster ? (int) my_pid : -((int) my_pid),
|
amPostmaster ? (int) my_pid : -((int) my_pid),
|
||||||
DataDir);
|
DataDir);
|
||||||
|
errno = 0;
|
||||||
if (write(fd, buffer, strlen(buffer)) != strlen(buffer))
|
if (write(fd, buffer, strlen(buffer)) != strlen(buffer))
|
||||||
{
|
{
|
||||||
int save_errno = errno;
|
int save_errno = errno;
|
||||||
|
|
||||||
close(fd);
|
close(fd);
|
||||||
unlink(filename);
|
unlink(filename);
|
||||||
errno = save_errno;
|
/* if write didn't set errno, assume problem is no disk space */
|
||||||
|
errno = save_errno ? save_errno : ENOSPC;
|
||||||
elog(FATAL, "Can't write lock file %s: %m", filename);
|
elog(FATAL, "Can't write lock file %s: %m", filename);
|
||||||
}
|
}
|
||||||
close(fd);
|
close(fd);
|
||||||
@ -794,9 +796,13 @@ RecordSharedMemoryInLockFile(IpcMemoryKey shmKey, IpcMemoryId shmId)
|
|||||||
* update should appear atomic to onlookers.
|
* update should appear atomic to onlookers.
|
||||||
*/
|
*/
|
||||||
len = strlen(buffer);
|
len = strlen(buffer);
|
||||||
|
errno = 0;
|
||||||
if (lseek(fd, (off_t) 0, SEEK_SET) != 0 ||
|
if (lseek(fd, (off_t) 0, SEEK_SET) != 0 ||
|
||||||
(int) write(fd, buffer, len) != len)
|
(int) write(fd, buffer, len) != len)
|
||||||
{
|
{
|
||||||
|
/* if write didn't set errno, assume problem is no disk space */
|
||||||
|
if (errno == 0)
|
||||||
|
errno = ENOSPC;
|
||||||
elog(DEBUG, "Failed to write %s: %m", directoryLockFile);
|
elog(DEBUG, "Failed to write %s: %m", directoryLockFile);
|
||||||
close(fd);
|
close(fd);
|
||||||
return;
|
return;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user