114 #define BootstrapTimeLineID 1
143 bool XLOG_DEBUG =
false;
153 #define NUM_XLOGINSERT_LOCKS 8
176 #ifdef HAVE_FSYNC_WRITETHROUGH
576 #define INSERT_FREESPACE(endptr) \
577 (((endptr) % XLOG_BLCKSZ == 0) ? 0 : (XLOG_BLCKSZ - (endptr) % XLOG_BLCKSZ))
580 #define NextBufIdx(idx) \
581 (((idx) == XLogCtl->XLogCacheBlck) ? 0 : ((idx) + 1))
587 #define XLogRecPtrToBufIdx(recptr) \
588 (((recptr) / XLOG_BLCKSZ) % (XLogCtl->XLogCacheBlck + 1))
593 #define UsableBytesInPage (XLOG_BLCKSZ - SizeOfXLogShortPHD)
599 #define ConvertToXSegs(x, segsize) XLogMBVarToSegs((x), (segsize))
735 bool topxid_included)
742 bool isLogSwitch = (rechdr->
xl_rmid == RM_XLOG_ID &&
754 elog(
ERROR,
"cannot make new WAL entries during recovery");
824 (!prevDoPageWrites ||
855 rdata_crc = rechdr->
xl_crc;
858 rechdr->
xl_crc = rdata_crc;
865 StartPos, EndPos, insertTLI);
907 if (StartPos / XLOG_BLCKSZ != EndPos / XLOG_BLCKSZ)
925 TRACE_POSTGRESQL_WAL_SWITCH();
936 if (StartPos / XLOG_BLCKSZ != EndPos / XLOG_BLCKSZ)
940 if (offset == EndPos % XLOG_BLCKSZ)
956 char *errormsg = NULL;
970 for (; rdata != NULL; rdata = rdata->
next)
993 errormsg ? errormsg :
"no error message");
999 debug_reader->
record = decoded;
1001 debug_reader->
record = NULL;
1048 uint64 startbytepos;
1069 startbytepos =
Insert->CurrBytePos;
1070 endbytepos = startbytepos + size;
1071 prevbytepos =
Insert->PrevBytePos;
1072 Insert->CurrBytePos = endbytepos;
1073 Insert->PrevBytePos = startbytepos;
1103 uint64 startbytepos;
1118 startbytepos =
Insert->CurrBytePos;
1124 *EndPos = *StartPos = ptr;
1128 endbytepos = startbytepos + size;
1129 prevbytepos =
Insert->PrevBytePos;
1141 Insert->CurrBytePos = endbytepos;
1142 Insert->PrevBytePos = startbytepos;
1186 while (rdata != NULL)
1188 char *rdata_data = rdata->
data;
1189 int rdata_len = rdata->
len;
1191 while (rdata_len > freespace)
1197 memcpy(currpos, rdata_data, freespace);
1198 rdata_data += freespace;
1199 rdata_len -= freespace;
1200 written += freespace;
1201 CurrPos += freespace;
1232 memcpy(currpos, rdata_data, rdata_len);
1233 currpos += rdata_len;
1234 CurrPos += rdata_len;
1235 freespace -= rdata_len;
1236 written += rdata_len;
1238 rdata = rdata->
next;
1240 Assert(written == write_len);
1256 CurrPos += freespace;
1264 while (CurrPos < EndPos)
1288 CurrPos += XLOG_BLCKSZ;
1297 if (CurrPos != EndPos)
1298 elog(
PANIC,
"space reserved for WAL record does not match what was written");
1320 static int lockToTry = -1;
1322 if (lockToTry == -1)
1447 elog(
PANIC,
"cannot wait without a PGPROC structure");
1451 bytepos =
Insert->CurrBytePos;
1463 if (upto > reservedUpto)
1466 (
errmsg(
"request to flush past end of generated WAL; request %X/%X, current position %X/%X",
1468 upto = reservedUpto;
1480 finishedUpto = reservedUpto;
1501 insertingat, &insertingat))
1512 }
while (insertingat < upto);
1515 finishedUpto = insertingat;
1517 return finishedUpto;
1541 static uint64 cachedPage = 0;
1542 static char *cachedPos = NULL;
1549 if (ptr / XLOG_BLCKSZ == cachedPage)
1553 return cachedPos + ptr % XLOG_BLCKSZ;
1580 expectedEndPtr = ptr;
1581 expectedEndPtr += XLOG_BLCKSZ - ptr % XLOG_BLCKSZ;
1584 if (expectedEndPtr != endptr)
1609 initializedUpto = ptr;
1616 if (expectedEndPtr != endptr)
1617 elog(
PANIC,
"could not find WAL buffer for %X/%X",
1633 cachedPage = ptr / XLOG_BLCKSZ;
1639 return cachedPos + ptr % XLOG_BLCKSZ;
1667 seg_offset = XLOG_BLCKSZ;
1710 seg_offset = XLOG_BLCKSZ;
1717 seg_offset += fullpages * XLOG_BLCKSZ + bytesleft;
1741 offset = ptr % XLOG_BLCKSZ;
1845 TRACE_POSTGRESQL_WAL_BUFFER_WRITE_DIRTY_START();
1846 WriteRqst.
Write = OldPageRqstPtr;
1847 WriteRqst.
Flush = 0;
1851 TRACE_POSTGRESQL_WAL_BUFFER_WRITE_DIRTY_DONE();
1864 NewPageEndPtr = NewPageBeginPtr + XLOG_BLCKSZ;
1874 MemSet((
char *) NewPage, 0, XLOG_BLCKSZ);
1882 NewPage->xlp_tli = tli;
1883 NewPage->xlp_pageaddr = NewPageBeginPtr;
1900 if (
Insert->runningBackups == 0)
1932 if (XLOG_DEBUG && npages > 0)
1934 elog(
DEBUG1,
"initialized %d pages, up to %X/%X",
2021 recycleSegNo = (
XLogSegNo) ceil(((
double) lastredoptr + distance) /
2024 if (recycleSegNo < minSegNo)
2025 recycleSegNo = minSegNo;
2026 if (recycleSegNo > maxSegNo)
2027 recycleSegNo = maxSegNo;
2029 return recycleSegNo;
2069 bool last_iteration;
2114 elog(
PANIC,
"xlog write request %X/%X is past end of log %X/%X",
2169 finishing_seg = !ispartialpage &&
2172 if (last_iteration ||
2184 nbytes = npages * (
Size) XLOG_BLCKSZ;
2228 errmsg(
"could not write to log file %s "
2229 "at offset %u, length %zu: %m",
2230 xlogfname, startoffset, nleft)));
2234 startoffset += written;
2235 }
while (nleft > 0);
2292 if (flexible && npages == 0)
2378 WriteRqstPtr -= WriteRqstPtr % XLOG_BLCKSZ;
2483 if (!force && newMinRecoveryPoint < lsn)
2485 "xlog min recovery request %X/%X is past current point %X/%X",
2498 (
errmsg_internal(
"updated min recovery point to %X/%X on timeline %u",
2500 newMinRecoveryPointTLI)));
2538 elog(
LOG,
"xlog flush request %X/%X; write %X/%X; flush %X/%X",
2555 WriteRqstPtr = record;
2567 if (WriteRqstPtr < XLogCtl->LogwrtRqst.Write)
2635 WriteRqst.
Write = insertpos;
2636 WriteRqst.
Flush = insertpos;
2673 "xlog flush request %X/%X is not satisfied --- flushed only to %X/%X",
2706 bool flexible =
true;
2729 WriteRqst.
Write -= WriteRqst.
Write % XLOG_BLCKSZ;
2791 WriteRqst.
Flush = 0;
2796 elog(
LOG,
"xlog bg flush request write %X/%X; flush: %X/%X, current is write %X/%X; flush %X/%X",
2812 XLogWrite(WriteRqst, insertTLI, flexible);
2922 bool *added,
char *path)
2929 int open_flags = O_RDWR | O_CREAT | O_EXCL |
PG_BINARY;
2943 if (errno != ENOENT)
2946 errmsg(
"could not open file \"%s\": %m", path)));
2957 elog(
DEBUG2,
"creating and filling new WAL file");
2971 errmsg(
"could not create file \"%s\": %m", tmppath)));
3003 save_errno = errno ? errno : ENOSPC;
3021 errmsg(
"could not write to file \"%s\": %m", tmppath)));
3032 errmsg(
"could not fsync file \"%s\": %m", tmppath)));
3039 errmsg(
"could not close file \"%s\": %m", tmppath)));
3046 installed_segno = logsegno;
3062 elog(
DEBUG2,
"done creating and filling new WAL file");
3109 errmsg(
"could not open file \"%s\": %m", path)));
3148 errmsg(
"could not open file \"%s\": %m", path)));
3162 errmsg(
"could not create file \"%s\": %m", tmppath)));
3171 nread = upto - nbytes;
3177 if (nread <
sizeof(buffer))
3178 memset(buffer.
data, 0,
sizeof(buffer));
3184 if (nread >
sizeof(buffer))
3185 nread =
sizeof(buffer);
3187 r =
read(srcfd, buffer.
data, nread);
3193 errmsg(
"could not read file \"%s\": %m",
3198 errmsg(
"could not read file \"%s\": read %d of %zu",
3199 path, r, (
Size) nread)));
3205 if ((
int)
write(
fd, buffer.
data,
sizeof(buffer)) != (
int)
sizeof(buffer))
3207 int save_errno = errno;
3214 errno = save_errno ? save_errno : ENOSPC;
3218 errmsg(
"could not write to file \"%s\": %m", tmppath)));
3227 errmsg(
"could not fsync file \"%s\": %m", tmppath)));
3233 errmsg(
"could not close file \"%s\": %m", tmppath)));
3238 errmsg(
"could not close file \"%s\": %m", path)));
3244 elog(
ERROR,
"InstallXLogFileSegment should not have failed");
3278 struct stat stat_buf;
3299 while (
stat(path, &stat_buf) == 0)
3301 if ((*segno) >= max_segno)
3341 errmsg(
"could not open file \"%s\": %m", path)));
3360 #if defined(USE_POSIX_FADVISE) && defined(POSIX_FADV_DONTNEED)
3362 (void) posix_fadvise(
openLogFile, 0, 0, POSIX_FADV_DONTNEED);
3368 int save_errno = errno;
3374 errmsg(
"could not close file \"%s\": %m", xlogfname)));
3440 int save_errno = errno;
3447 if (segno <= lastRemovedSegNo)
3455 errmsg(
"requested WAL segment %s has already been removed",
3477 return lastRemovedSegNo;
3511 elog(
DEBUG2,
"removing all temporary WAL segments");
3518 if (strncmp(xlde->
d_name,
"xlogtemp.", 9) != 0)
3523 elog(
DEBUG2,
"removed temporary WAL segment \"%s\"", path);
3559 elog(
DEBUG2,
"attempting to remove WAL segments older than log file %s",
3582 if (strcmp(xlde->
d_name + 8, lastoff + 8) <= 0)
3628 recycleSegNo = endLogSegNo + 10;
3635 elog(
DEBUG2,
"attempting to remove WAL segments newer than log file %s",
3651 if (strncmp(xlde->
d_name, switchseg, 8) < 0 &&
3652 strcmp(xlde->
d_name + 8, switchseg + 8) > 0)
3690 const char *segname = segment_de->
d_name;
3700 *endlogSegNo <= recycleSegNo &&
3704 true, recycleSegNo, insertTLI))
3735 if (rename(path, newpath) != 0)
3739 errmsg(
"could not rename file \"%s\": %m",
3775 struct stat stat_buf;
3781 (
errmsg(
"required WAL directory \"%s\" does not exist",
3786 if (
stat(path, &stat_buf) == 0)
3791 (
errmsg(
"required WAL directory \"%s\" does not exist",
3797 (
errmsg(
"creating missing WAL directory \"%s\"", path)));
3800 (
errmsg(
"could not create missing directory \"%s\": %m",
3825 elog(
DEBUG2,
"removing WAL backup history file \"%s\"",
3866 (
errcode(ERRCODE_INTERNAL_ERROR),
3867 errmsg(
"could not generate secret authorization token")));
3938 errmsg(
"could not create file \"%s\": %m",
3950 errmsg(
"could not write to file \"%s\": %m",
3959 errmsg(
"could not fsync file \"%s\": %m",
3966 errmsg(
"could not close file \"%s\": %m",
3975 static char wal_segsz_str[20];
3986 errmsg(
"could not open file \"%s\": %m",
3996 errmsg(
"could not read file \"%s\": %m",
4001 errmsg(
"could not read file \"%s\": read %d of %zu",
4017 (
errmsg(
"database files are incompatible with server"),
4018 errdetail(
"The database cluster was initialized with PG_CONTROL_VERSION %d (0x%08x),"
4019 " but the server was compiled with PG_CONTROL_VERSION %d (0x%08x).",
4022 errhint(
"This could be a problem of mismatched byte ordering. It looks like you need to initdb.")));
4026 (
errmsg(
"database files are incompatible with server"),
4027 errdetail(
"The database cluster was initialized with PG_CONTROL_VERSION %d,"
4028 " but the server was compiled with PG_CONTROL_VERSION %d.",
4030 errhint(
"It looks like you need to initdb.")));
4041 (
errmsg(
"incorrect checksum in control file")));
4050 (
errmsg(
"database files are incompatible with server"),
4051 errdetail(
"The database cluster was initialized with CATALOG_VERSION_NO %d,"
4052 " but the server was compiled with CATALOG_VERSION_NO %d.",
4054 errhint(
"It looks like you need to initdb.")));
4057 (
errmsg(
"database files are incompatible with server"),
4058 errdetail(
"The database cluster was initialized with MAXALIGN %d,"
4059 " but the server was compiled with MAXALIGN %d.",
4061 errhint(
"It looks like you need to initdb.")));
4064 (
errmsg(
"database files are incompatible with server"),
4065 errdetail(
"The database cluster appears to use a different floating-point number format than the server executable."),
4066 errhint(
"It looks like you need to initdb.")));
4069 (
errmsg(
"database files are incompatible with server"),
4070 errdetail(
"The database cluster was initialized with BLCKSZ %d,"
4071 " but the server was compiled with BLCKSZ %d.",
4073 errhint(
"It looks like you need to recompile or initdb.")));
4076 (
errmsg(
"database files are incompatible with server"),
4077 errdetail(
"The database cluster was initialized with RELSEG_SIZE %d,"
4078 " but the server was compiled with RELSEG_SIZE %d.",
4080 errhint(
"It looks like you need to recompile or initdb.")));
4083 (
errmsg(
"database files are incompatible with server"),
4084 errdetail(
"The database cluster was initialized with XLOG_BLCKSZ %d,"
4085 " but the server was compiled with XLOG_BLCKSZ %d.",
4087 errhint(
"It looks like you need to recompile or initdb.")));
4090 (
errmsg(
"database files are incompatible with server"),
4091 errdetail(
"The database cluster was initialized with NAMEDATALEN %d,"
4092 " but the server was compiled with NAMEDATALEN %d.",
4094 errhint(
"It looks like you need to recompile or initdb.")));
4097 (
errmsg(
"database files are incompatible with server"),
4098 errdetail(
"The database cluster was initialized with INDEX_MAX_KEYS %d,"
4099 " but the server was compiled with INDEX_MAX_KEYS %d.",
4101 errhint(
"It looks like you need to recompile or initdb.")));
4104 (
errmsg(
"database files are incompatible with server"),
4105 errdetail(
"The database cluster was initialized with TOAST_MAX_CHUNK_SIZE %d,"
4106 " but the server was compiled with TOAST_MAX_CHUNK_SIZE %d.",
4108 errhint(
"It looks like you need to recompile or initdb.")));
4111 (
errmsg(
"database files are incompatible with server"),
4112 errdetail(
"The database cluster was initialized with LOBLKSIZE %d,"
4113 " but the server was compiled with LOBLKSIZE %d.",
4115 errhint(
"It looks like you need to recompile or initdb.")));
4117 #ifdef USE_FLOAT8_BYVAL
4120 (
errmsg(
"database files are incompatible with server"),
4121 errdetail(
"The database cluster was initialized without USE_FLOAT8_BYVAL"
4122 " but the server was compiled with USE_FLOAT8_BYVAL."),
4123 errhint(
"It looks like you need to recompile or initdb.")));
4127 (
errmsg(
"database files are incompatible with server"),
4128 errdetail(
"The database cluster was initialized with USE_FLOAT8_BYVAL"
4129 " but the server was compiled without USE_FLOAT8_BYVAL."),
4130 errhint(
"It looks like you need to recompile or initdb.")));
4137 errmsg_plural(
"WAL segment size must be a power of two between 1 MB and 1 GB, but the control file specifies %d byte",
4138 "WAL segment size must be a power of two between 1 MB and 1 GB, but the control file specifies %d bytes",
4149 errmsg(
"\"min_wal_size\" must be at least twice \"wal_segment_size\"")));
4153 errmsg(
"\"max_wal_size\" must be at least twice \"wal_segment_size\"")));
4225 return nextUnloggedLSN;
4314 foreach(l, elemlist)
4316 char *tok = (
char *)
lfirst(l);
4322 for (rmid = 0; rmid <=
RM_MAX_ID; rmid++)
4324 newwalconsistency[rmid] =
true;
4331 for (rmid = 0; rmid <=
RM_MAX_ID; rmid++)
4336 newwalconsistency[rmid] =
true;
4368 memcpy(*extra, newwalconsistency, (
RM_MAX_ID + 1) *
sizeof(
bool));
4434 return "(disabled)";
4552 if (walDebugCxt == NULL)
4569 if (foundCFile || foundXLog)
4572 Assert(foundCFile && foundXLog);
4577 if (localControlFile)
4578 pfree(localControlFile);
4587 if (localControlFile)
4590 pfree(localControlFile);
4623 allocptr = (
char *)
TYPEALIGN(XLOG_BLCKSZ, allocptr);
4654 uint64 sysidentifier;
4674 sysidentifier = ((uint64) tv.tv_sec) << 32;
4675 sysidentifier |= ((uint64) tv.tv_usec) << 12;
4676 sysidentifier |= getpid() & 0xFFF;
4679 buffer = (
char *)
palloc(XLOG_BLCKSZ + XLOG_BLCKSZ);
4681 memset(page, 0, XLOG_BLCKSZ);
4738 *(recptr++) =
sizeof(checkPoint);
4739 memcpy(recptr, &checkPoint,
sizeof(checkPoint));
4740 recptr +=
sizeof(checkPoint);
4768 errmsg(
"could not write bootstrap write-ahead log file: %m")));
4776 errmsg(
"could not fsync bootstrap write-ahead log file: %m")));
4782 errmsg(
"could not close bootstrap write-ahead log file: %m")));
4813 static char buf[128];
4816 "%Y-%m-%d %H:%M:%S %Z",
4833 Assert(endTLI != newTLI);
4855 if (endLogSegNo == startLogSegNo)
4879 int save_errno = errno;
4885 errmsg(
"could not close file \"%s\": %m", xlogfname)));
4909 "recovery_end_command",
4999 (
errmsg(
"WAL was generated with wal_level=minimal, cannot continue recovering"),
5000 errdetail(
"This happens if you temporarily set wal_level=minimal on the server."),
5001 errhint(
"Use a backup taken after setting wal_level to higher than minimal.")));
5040 bool haveBackupLabel;
5044 bool performedWalRecovery;
5049 bool promoted =
false;
5065 (
errmsg(
"control file contains invalid checkpoint location")));
5076 (
errmsg(
"database system was shut down at %s",
5082 (
errmsg(
"database system was shut down in recovery at %s",
5088 (
errmsg(
"database system shutdown was interrupted; last known up at %s",
5094 (
errmsg(
"database system was interrupted while in recovery at %s",
5096 errhint(
"This probably means that some data is corrupted and"
5097 " you will have to use the last backup for recovery.")));
5102 (
errmsg(
"database system was interrupted while in recovery at log time %s",
5104 errhint(
"If this has occurred more than once some data might be corrupted"
5105 " and you might need to choose an earlier recovery target.")));
5110 (
errmsg(
"database system was interrupted; last known up at %s",
5116 (
errmsg(
"control file contains invalid database cluster state")));
5120 #ifdef XLOG_REPLAY_DELAY
5170 &haveBackupLabel, &haveTblspcMap);
5321 if (haveBackupLabel)
5427 running.
xcnt = nxids;
5436 running.
xids = xids;
5448 performedWalRecovery =
true;
5451 performedWalRecovery =
false;
5457 EndOfLog = endOfRecoveryInfo->
endOfLog;
5500 (
errmsg(
"WAL ends before end of online backup"),
5501 errhint(
"All WAL generated while online backup was taken must be available at recovery.")));
5504 (
errmsg(
"WAL ends before consistent recovery point")));
5550 (
errmsg(
"selected new timeline ID: %u", newTLI)));
5583 (
errmsg(
"archive recovery complete")));