mirror of
https://github.com/zebrajr/postgres.git
synced 2025-12-06 12:20:15 +01:00
In 9.3, there's no particular limit on the number of bgworkers; instead, we just count up the number that are actually registered, and use that to set MaxBackends. However, that approach causes problems for Hot Standby, which needs both MaxBackends and the size of the lock table to be the same on the standby as on the master, yet it may not be desirable to run the same bgworkers in both places. 9.3 handles that by failing to notice the problem, which will probably work fine in nearly all cases anyway, but is not theoretically sound. A further problem with simply counting the number of registered workers is that new workers can't be registered without a postmaster restart. This is inconvenient for administrators, since bouncing the postmaster causes an interruption of service. Moreover, there are a number of applications for background processes where, by necessity, the background process must be started on the fly (e.g. parallel query). While this patch doesn't actually make it possible to register new background workers after startup time, it's a necessary prerequisite. Patch by me. Review by Michael Paquier.
146 lines
3.9 KiB
C
146 lines
3.9 KiB
C
/*-------------------------------------------------------------------------
|
|
*
|
|
* xlogdesc.c
|
|
* rmgr descriptor routines for access/transam/xlog.c
|
|
*
|
|
* Portions Copyright (c) 1996-2013, 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 "common/relpath.h"
|
|
#include "utils/guc.h"
|
|
#include "utils/timestamp.h"
|
|
|
|
/*
|
|
* GUC support
|
|
*/
|
|
const struct config_enum_entry wal_level_options[] = {
|
|
{"minimal", WAL_LEVEL_MINIMAL, false},
|
|
{"archive", WAL_LEVEL_ARCHIVE, false},
|
|
{"hot_standby", WAL_LEVEL_HOT_STANDBY, false},
|
|
{NULL, 0, false}
|
|
};
|
|
|
|
void
|
|
xlog_desc(StringInfo buf, uint8 xl_info, char *rec)
|
|
{
|
|
uint8 info = xl_info & ~XLR_INFO_MASK;
|
|
|
|
if (info == XLOG_CHECKPOINT_SHUTDOWN ||
|
|
info == XLOG_CHECKPOINT_ONLINE)
|
|
{
|
|
CheckPoint *checkpoint = (CheckPoint *) rec;
|
|
|
|
appendStringInfo(buf, "checkpoint: 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 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->oldestActiveXid,
|
|
(info == XLOG_CHECKPOINT_SHUTDOWN) ? "shutdown" : "online");
|
|
}
|
|
else if (info == XLOG_NOOP)
|
|
{
|
|
appendStringInfo(buf, "xlog no-op");
|
|
}
|
|
else if (info == XLOG_NEXTOID)
|
|
{
|
|
Oid nextOid;
|
|
|
|
memcpy(&nextOid, rec, sizeof(Oid));
|
|
appendStringInfo(buf, "nextOid: %u", nextOid);
|
|
}
|
|
else if (info == XLOG_SWITCH)
|
|
{
|
|
appendStringInfo(buf, "xlog switch");
|
|
}
|
|
else if (info == XLOG_RESTORE_POINT)
|
|
{
|
|
xl_restore_point *xlrec = (xl_restore_point *) rec;
|
|
|
|
appendStringInfo(buf, "restore point: %s", xlrec->rp_name);
|
|
|
|
}
|
|
else if (info == XLOG_FPI)
|
|
{
|
|
BkpBlock *bkp = (BkpBlock *) rec;
|
|
|
|
appendStringInfo(buf, "full-page image: %s block %u",
|
|
relpathperm(bkp->node, bkp->fork),
|
|
bkp->block);
|
|
}
|
|
else if (info == XLOG_BACKUP_END)
|
|
{
|
|
XLogRecPtr startpoint;
|
|
|
|
memcpy(&startpoint, rec, sizeof(XLogRecPtr));
|
|
appendStringInfo(buf, "backup end: %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, "parameter change: max_connections=%d max_worker_processes=%d max_prepared_xacts=%d max_locks_per_xact=%d wal_level=%s",
|
|
xlrec.MaxConnections,
|
|
xlrec.max_worker_processes,
|
|
xlrec.max_prepared_xacts,
|
|
xlrec.max_locks_per_xact,
|
|
wal_level_str);
|
|
}
|
|
else if (info == XLOG_FPW_CHANGE)
|
|
{
|
|
bool fpw;
|
|
|
|
memcpy(&fpw, rec, sizeof(bool));
|
|
appendStringInfo(buf, "full_page_writes: %s", 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, "end_of_recovery: tli %u; prev tli %u; time %s",
|
|
xlrec.ThisTimeLineID, xlrec.PrevTimeLineID,
|
|
timestamptz_to_str(xlrec.end_time));
|
|
}
|
|
else
|
|
appendStringInfo(buf, "UNKNOWN");
|
|
}
|