mirror of
https://github.com/postgres/postgres.git
synced 2025-06-22 02:52:08 +03:00
Since its introduction, max_wal_senders is counted as part of max_connections when it comes to define how many connection slots can be used for replication connections with a WAL sender context. This can lead to confusion for some users, as it could be possible to block a base backup or replication from happening because other backend sessions are already taken for other purposes by an application, and superuser-only connection slots are not a correct solution to handle that case. This commit makes max_wal_senders independent of max_connections for its handling of PGPROC entries in ProcGlobal, meaning that connection slots for WAL senders are handled using their own free queue, like autovacuum workers and bgworkers. One compatibility issue that this change creates is that a standby now requires to have a value of max_wal_senders at least equal to its primary. So, if a standby created enforces the value of max_wal_senders to be lower than that, then this could break failovers. Normally this should not be an issue though, as any settings of a standby are inherited from its primary as postgresql.conf gets normally copied as part of a base backup, so parameters would be consistent. Author: Alexander Kukushkin Reviewed-by: Kyotaro Horiguchi, Petr Jelínek, Masahiko Sawada, Oleksii Kliukin Discussion: https://postgr.es/m/CAFh8B=nBzHQeYAu0b8fjK-AF1X4+_p6GRtwG+cCgs6Vci2uRuQ@mail.gmail.com
190 lines
4.8 KiB
C
190 lines
4.8 KiB
C
/*-------------------------------------------------------------------------
|
|
*
|
|
* xlogdesc.c
|
|
* rmgr descriptor routines for access/transam/xlog.c
|
|
*
|
|
* Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
|
|
* Portions Copyright (c) 1994, Regents of the University of California
|
|
*
|
|
*
|
|
* IDENTIFICATION
|
|
* src/backend/access/rmgrdesc/xlogdesc.c
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
#include "postgres.h"
|
|
|
|
#include "access/xlog.h"
|
|
#include "access/xlog_internal.h"
|
|
#include "catalog/pg_control.h"
|
|
#include "utils/guc.h"
|
|
#include "utils/timestamp.h"
|
|
|
|
/*
|
|
* GUC support
|
|
*/
|
|
const struct config_enum_entry wal_level_options[] = {
|
|
{"minimal", WAL_LEVEL_MINIMAL, false},
|
|
{"replica", WAL_LEVEL_REPLICA, false},
|
|
{"archive", WAL_LEVEL_REPLICA, true}, /* deprecated */
|
|
{"hot_standby", WAL_LEVEL_REPLICA, true}, /* deprecated */
|
|
{"logical", WAL_LEVEL_LOGICAL, false},
|
|
{NULL, 0, false}
|
|
};
|
|
|
|
void
|
|
xlog_desc(StringInfo buf, XLogReaderState *record)
|
|
{
|
|
char *rec = XLogRecGetData(record);
|
|
uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
|
|
|
|
if (info == XLOG_CHECKPOINT_SHUTDOWN ||
|
|
info == XLOG_CHECKPOINT_ONLINE)
|
|
{
|
|
CheckPoint *checkpoint = (CheckPoint *) rec;
|
|
|
|
appendStringInfo(buf, "redo %X/%X; "
|
|
"tli %u; prev tli %u; fpw %s; xid %u:%u; oid %u; multi %u; offset %u; "
|
|
"oldest xid %u in DB %u; oldest multi %u in DB %u; "
|
|
"oldest/newest commit timestamp xid: %u/%u; "
|
|
"oldest running xid %u; %s",
|
|
(uint32) (checkpoint->redo >> 32), (uint32) checkpoint->redo,
|
|
checkpoint->ThisTimeLineID,
|
|
checkpoint->PrevTimeLineID,
|
|
checkpoint->fullPageWrites ? "true" : "false",
|
|
checkpoint->nextXidEpoch, checkpoint->nextXid,
|
|
checkpoint->nextOid,
|
|
checkpoint->nextMulti,
|
|
checkpoint->nextMultiOffset,
|
|
checkpoint->oldestXid,
|
|
checkpoint->oldestXidDB,
|
|
checkpoint->oldestMulti,
|
|
checkpoint->oldestMultiDB,
|
|
checkpoint->oldestCommitTsXid,
|
|
checkpoint->newestCommitTsXid,
|
|
checkpoint->oldestActiveXid,
|
|
(info == XLOG_CHECKPOINT_SHUTDOWN) ? "shutdown" : "online");
|
|
}
|
|
else if (info == XLOG_NEXTOID)
|
|
{
|
|
Oid nextOid;
|
|
|
|
memcpy(&nextOid, rec, sizeof(Oid));
|
|
appendStringInfo(buf, "%u", nextOid);
|
|
}
|
|
else if (info == XLOG_RESTORE_POINT)
|
|
{
|
|
xl_restore_point *xlrec = (xl_restore_point *) rec;
|
|
|
|
appendStringInfoString(buf, xlrec->rp_name);
|
|
}
|
|
else if (info == XLOG_FPI || info == XLOG_FPI_FOR_HINT)
|
|
{
|
|
/* no further information to print */
|
|
}
|
|
else if (info == XLOG_BACKUP_END)
|
|
{
|
|
XLogRecPtr startpoint;
|
|
|
|
memcpy(&startpoint, rec, sizeof(XLogRecPtr));
|
|
appendStringInfo(buf, "%X/%X",
|
|
(uint32) (startpoint >> 32), (uint32) startpoint);
|
|
}
|
|
else if (info == XLOG_PARAMETER_CHANGE)
|
|
{
|
|
xl_parameter_change xlrec;
|
|
const char *wal_level_str;
|
|
const struct config_enum_entry *entry;
|
|
|
|
memcpy(&xlrec, rec, sizeof(xl_parameter_change));
|
|
|
|
/* Find a string representation for wal_level */
|
|
wal_level_str = "?";
|
|
for (entry = wal_level_options; entry->name; entry++)
|
|
{
|
|
if (entry->val == xlrec.wal_level)
|
|
{
|
|
wal_level_str = entry->name;
|
|
break;
|
|
}
|
|
}
|
|
|
|
appendStringInfo(buf, "max_connections=%d max_worker_processes=%d "
|
|
"max_wal_senders=%d max_prepared_xacts=%d "
|
|
"max_locks_per_xact=%d wal_level=%s "
|
|
"wal_log_hints=%s track_commit_timestamp=%s",
|
|
xlrec.MaxConnections,
|
|
xlrec.max_wal_senders,
|
|
xlrec.max_worker_processes,
|
|
xlrec.max_prepared_xacts,
|
|
xlrec.max_locks_per_xact,
|
|
wal_level_str,
|
|
xlrec.wal_log_hints ? "on" : "off",
|
|
xlrec.track_commit_timestamp ? "on" : "off");
|
|
}
|
|
else if (info == XLOG_FPW_CHANGE)
|
|
{
|
|
bool fpw;
|
|
|
|
memcpy(&fpw, rec, sizeof(bool));
|
|
appendStringInfoString(buf, fpw ? "true" : "false");
|
|
}
|
|
else if (info == XLOG_END_OF_RECOVERY)
|
|
{
|
|
xl_end_of_recovery xlrec;
|
|
|
|
memcpy(&xlrec, rec, sizeof(xl_end_of_recovery));
|
|
appendStringInfo(buf, "tli %u; prev tli %u; time %s",
|
|
xlrec.ThisTimeLineID, xlrec.PrevTimeLineID,
|
|
timestamptz_to_str(xlrec.end_time));
|
|
}
|
|
}
|
|
|
|
const char *
|
|
xlog_identify(uint8 info)
|
|
{
|
|
const char *id = NULL;
|
|
|
|
switch (info & ~XLR_INFO_MASK)
|
|
{
|
|
case XLOG_CHECKPOINT_SHUTDOWN:
|
|
id = "CHECKPOINT_SHUTDOWN";
|
|
break;
|
|
case XLOG_CHECKPOINT_ONLINE:
|
|
id = "CHECKPOINT_ONLINE";
|
|
break;
|
|
case XLOG_NOOP:
|
|
id = "NOOP";
|
|
break;
|
|
case XLOG_NEXTOID:
|
|
id = "NEXTOID";
|
|
break;
|
|
case XLOG_SWITCH:
|
|
id = "SWITCH";
|
|
break;
|
|
case XLOG_BACKUP_END:
|
|
id = "BACKUP_END";
|
|
break;
|
|
case XLOG_PARAMETER_CHANGE:
|
|
id = "PARAMETER_CHANGE";
|
|
break;
|
|
case XLOG_RESTORE_POINT:
|
|
id = "RESTORE_POINT";
|
|
break;
|
|
case XLOG_FPW_CHANGE:
|
|
id = "FPW_CHANGE";
|
|
break;
|
|
case XLOG_END_OF_RECOVERY:
|
|
id = "END_OF_RECOVERY";
|
|
break;
|
|
case XLOG_FPI:
|
|
id = "FPI";
|
|
break;
|
|
case XLOG_FPI_FOR_HINT:
|
|
id = "FPI_FOR_HINT";
|
|
break;
|
|
}
|
|
|
|
return id;
|
|
}
|