mirror of
https://github.com/EnterpriseDB/repmgr.git
synced 2026-03-23 07:06:30 +00:00
Compare commits
12 Commits
dev/author
...
v5.5.0+deb
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c0d9dc6dac | ||
|
|
836894c965 | ||
|
|
7f3a26f0d9 | ||
|
|
a469221e28 | ||
|
|
c6d9f38458 | ||
|
|
5abdbb0d39 | ||
|
|
8f27e3bc5d | ||
|
|
b92d43d136 | ||
|
|
4a28c57bc7 | ||
|
|
f69485c0ba | ||
|
|
b4a0938081 | ||
|
|
569f906003 |
7
.github/CODEOWNERS
vendored
Normal file
7
.github/CODEOWNERS
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
# Each line is a file pattern followed by one or more owners.
|
||||
|
||||
# These owners will be the default owners for everything in
|
||||
# the repo. Unless a later match takes precedence,
|
||||
# @global-owner1 and @global-owner2 will be requested for
|
||||
# review when someone opens a pull request.
|
||||
* @EnterpriseDB/repmgr-dev
|
||||
7
HISTORY
7
HISTORY
@@ -1,4 +1,9 @@
|
||||
5.4.1 2023-??-??
|
||||
5.5.0 2024-11-20
|
||||
Support for PostgreSQL 17 added
|
||||
Fix warnings detected by the -Wshadow=compatible-local
|
||||
added in PostgreSQL 16
|
||||
|
||||
5.4.1 2023-07-04
|
||||
repmgrd: ensure witness node metadata is updated (Ian)
|
||||
|
||||
5.4.0 2023-03-16
|
||||
|
||||
@@ -32,7 +32,9 @@ DATA = \
|
||||
repmgr--5.2--5.3.sql \
|
||||
repmgr--5.3.sql \
|
||||
repmgr--5.3--5.4.sql \
|
||||
repmgr--5.4.sql
|
||||
repmgr--5.4.sql \
|
||||
repmgr--5.4--5.5.sql \
|
||||
repmgr--5.5.sql
|
||||
|
||||
REGRESS = repmgr_extension
|
||||
|
||||
|
||||
15
README.md
15
README.md
@@ -7,8 +7,9 @@ replication capabilities with utilities to set up standby servers, monitor
|
||||
replication, and perform administrative tasks such as failover or switchover
|
||||
operations.
|
||||
|
||||
The most recent `repmgr` version (5.3.2) supports all PostgreSQL versions from
|
||||
9.5 to 15. PostgreSQL 9.4 is also supported, with some restrictions.
|
||||
The most recent `repmgr` version (5.5.x) supports all PostgreSQL versions from
|
||||
13 to 17. Despite it could be used with some older ones, some features might not
|
||||
be available, however, it's strongly recommended to use the latest version.
|
||||
|
||||
`repmgr` is distributed under the GNU GPL 3 and maintained by EnterpriseDB.
|
||||
|
||||
@@ -56,8 +57,6 @@ There is a mailing list/forum to discuss contributions or issues:
|
||||
|
||||
* https://groups.google.com/group/repmgr
|
||||
|
||||
The IRC channel #repmgr is registered with freenode.
|
||||
|
||||
Please report bugs and other issues to:
|
||||
|
||||
* https://github.com/EnterpriseDB/repmgr
|
||||
@@ -69,6 +68,14 @@ news are always welcome.
|
||||
|
||||
Thanks from the repmgr core team.
|
||||
|
||||
* Ian Barwick
|
||||
* Israel Barth
|
||||
* Mario González
|
||||
* Martín Marqués
|
||||
* Gianni Ciolli
|
||||
|
||||
Past contributors:
|
||||
|
||||
* Jaime Casanova
|
||||
* Abhijit Menon-Sen
|
||||
* Simon Riggs
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
AC_INIT([repmgr], [5.4.0], [repmgr@googlegroups.com], [repmgr], [https://repmgr.org/])
|
||||
AC_INIT([repmgr], [5.5.0], [repmgr@googlegroups.com], [repmgr], [https://repmgr.org/])
|
||||
|
||||
AC_COPYRIGHT([Copyright (c) 2010-2021, EnterpriseDB Corporation])
|
||||
AC_COPYRIGHT([Copyright (c) 2010-2024, EnterpriseDB Corporation])
|
||||
|
||||
AC_CONFIG_HEADER(config.h)
|
||||
|
||||
|
||||
58
dbutils.c
58
dbutils.c
@@ -1624,7 +1624,7 @@ get_ready_archive_files(PGconn *conn, const char *data_directory)
|
||||
|
||||
while ((arcdir_ent = readdir(arcdir)) != NULL)
|
||||
{
|
||||
struct stat statbuf;
|
||||
struct stat local_statbuf;
|
||||
char file_path[MAXPGPATH + sizeof(arcdir_ent->d_name)];
|
||||
int basenamelen = 0;
|
||||
|
||||
@@ -1634,7 +1634,7 @@ get_ready_archive_files(PGconn *conn, const char *data_directory)
|
||||
arcdir_ent->d_name);
|
||||
|
||||
/* skip non-files */
|
||||
if (stat(file_path, &statbuf) == 0 && !S_ISREG(statbuf.st_mode))
|
||||
if (stat(file_path, &local_statbuf) == 0 && !S_ISREG(local_statbuf.st_mode))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -1852,6 +1852,51 @@ get_wal_receiver_pid(PGconn *conn)
|
||||
/* =============================== */
|
||||
|
||||
|
||||
/*
|
||||
* Determine if the user associated with the current connection can execute CHECKPOINT command.
|
||||
* User must be a supersuer or a member of the pg_checkpoint default role (available from PostgreSQL 15).
|
||||
*/
|
||||
bool
|
||||
can_execute_checkpoint(PGconn *conn)
|
||||
{
|
||||
PQExpBufferData query;
|
||||
PGresult *res;
|
||||
bool has_pg_checkpoint_role = false;
|
||||
|
||||
/* superusers can do anything, no role check needed */
|
||||
if (is_superuser_connection(conn, NULL) == true)
|
||||
return true;
|
||||
|
||||
/* pg_checkpoint available from PostgreSQL 15 */
|
||||
if (PQserverVersion(conn) < 150000)
|
||||
return false;
|
||||
|
||||
initPQExpBuffer(&query);
|
||||
appendPQExpBufferStr(&query,
|
||||
" SELECT pg_catalog.pg_has_role('pg_checkpoint','USAGE') ");
|
||||
|
||||
res = PQexec(conn, query.data);
|
||||
|
||||
if (PQresultStatus(res) != PGRES_TUPLES_OK)
|
||||
{
|
||||
log_db_error(conn, query.data,
|
||||
_("can_execute_checkpoint(): unable to query user roles"));
|
||||
}
|
||||
else
|
||||
{
|
||||
has_pg_checkpoint_role = atobool(PQgetvalue(res, 0, 0));
|
||||
}
|
||||
termPQExpBuffer(&query);
|
||||
PQclear(res);
|
||||
|
||||
return has_pg_checkpoint_role;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Determine if the user associated with the current connection
|
||||
* has sufficient permissions to use pg_promote function
|
||||
*/
|
||||
bool
|
||||
can_execute_pg_promote(PGconn *conn)
|
||||
{
|
||||
@@ -1979,13 +2024,13 @@ connection_has_pg_monitor_role(PGconn *conn, const char *subrole)
|
||||
initPQExpBuffer(&query);
|
||||
appendPQExpBufferStr(&query,
|
||||
" SELECT CASE "
|
||||
" WHEN pg_catalog.pg_has_role('pg_monitor','MEMBER') "
|
||||
" WHEN pg_catalog.pg_has_role('pg_monitor','USAGE') "
|
||||
" THEN TRUE ");
|
||||
|
||||
if (subrole != NULL)
|
||||
{
|
||||
appendPQExpBuffer(&query,
|
||||
" WHEN pg_catalog.pg_has_role('%s','MEMBER') "
|
||||
" WHEN pg_catalog.pg_has_role('%s','USAGE') "
|
||||
" THEN TRUE ",
|
||||
subrole);
|
||||
}
|
||||
@@ -2492,7 +2537,10 @@ get_repmgr_extension_status(PGconn *conn, t_extension_versions *extversions)
|
||||
/* node management functions */
|
||||
/* ========================= */
|
||||
|
||||
/* assumes superuser connection */
|
||||
/*
|
||||
* Assumes the connection can execute CHECKPOINT command.
|
||||
* A check can be executed via 'can_execute_checkpoint' function.
|
||||
*/
|
||||
void
|
||||
checkpoint(PGconn *conn)
|
||||
{
|
||||
|
||||
@@ -453,6 +453,7 @@ TimeLineHistoryEntry *get_timeline_history(PGconn *repl_conn, TimeLineID tli);
|
||||
pid_t get_wal_receiver_pid(PGconn *conn);
|
||||
|
||||
/* user/role information functions */
|
||||
bool can_execute_checkpoint(PGconn *conn);
|
||||
bool can_execute_pg_promote(PGconn *conn);
|
||||
bool can_disable_walsender(PGconn *conn);
|
||||
bool connection_has_pg_monitor_role(PGconn *conn, const char *subrole);
|
||||
|
||||
@@ -16,9 +16,24 @@
|
||||
</para>
|
||||
|
||||
<!-- remember to update the release date in ../repmgr_version.h.in -->
|
||||
|
||||
<sect1 id="release-5.5.0">
|
||||
<title>Release 5.5.0</title>
|
||||
<para><emphasis>Wed 20 November, 2024</emphasis></para>
|
||||
<para>
|
||||
&repmgr; 5.5.0 is a major release.
|
||||
</para>
|
||||
<para>
|
||||
This release adds support for PostgreSQL 17
|
||||
</para>
|
||||
<para>
|
||||
Fixes warnings detected by the -Wshadow gcc flag added in PostgreSQL 16.
|
||||
</para>
|
||||
</sect1>
|
||||
|
||||
<sect1 id="release-5.4.1">
|
||||
<title id="release-current">Release 5.4.1</title>
|
||||
<para><emphasis>??? ?? ??????, 202?</emphasis></para>
|
||||
<para><emphasis>Tue 04 Jul, 2023</emphasis></para>
|
||||
<para>
|
||||
&repmgr; 5.4.1 is a minor release providing ...
|
||||
</para>
|
||||
|
||||
@@ -79,6 +79,10 @@
|
||||
Alternatively the meta-role <varname>pg_monitor</varname> can be granted, which includes membership
|
||||
of the above predefined roles.
|
||||
</para>
|
||||
<para>
|
||||
PostgreSQL 15 introduced the <varname>pg_checkpoint</varname> predefined role which allows a
|
||||
non-superuser &repmgr; database user to perform a CHECKPOINT command.
|
||||
</para>
|
||||
<para>
|
||||
Membership of these roles can be granted with e.g. <command>GRANT pg_read_all_stats TO repmgr</command>.
|
||||
</para>
|
||||
@@ -148,6 +152,8 @@
|
||||
<link linkend="repmgr-standby-switchover">repmgr standby switchover</link>. This can only
|
||||
be executed by a superuser; if the &repmgr; user is not a superuser,
|
||||
the <option>-S</option>/<option>--superuser</option> should be used.
|
||||
From PostgreSQL 15 the <varname>pg_checkpoint</varname> predefined role removes the need of
|
||||
superuser permissions to perform <command>CHECKPOINT</command> command.
|
||||
</simpara>
|
||||
<simpara>
|
||||
If &repmgr; is not able to execute <command>CHECKPOINT</command>,
|
||||
|
||||
@@ -77,7 +77,8 @@
|
||||
</para>
|
||||
<para>
|
||||
Note that a superuser connection is required to be able to execute the
|
||||
<command>CHECKPOINT</command> command.
|
||||
<command>CHECKPOINT</command> command. From PostgreSQL 15 the <varname>pg_checkpoint</varname>
|
||||
predefined role removes the need for superuser permissions to perform <command>CHECKPOINT</command> command.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
@@ -79,7 +79,8 @@
|
||||
<para>
|
||||
Note that <command>CHECKPOINT</command> requires database superuser permissions to execute.
|
||||
If the <literal>repmgr</literal> user is not a superuser, the name of a superuser should be
|
||||
provided with the <option>-S</option>/<option>--superuser</option> option.
|
||||
provided with the <option>-S</option>/<option>--superuser</option> option. From PostgreSQL 15 the <varname>pg_checkpoint</varname>
|
||||
predefined role removes the need for superuser permissions to perform <command>CHECKPOINT</command> command.
|
||||
</para>
|
||||
<para>
|
||||
If &repmgr; is unable to execute the <command>CHECKPOINT</command> command, the switchover
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
<abstract>
|
||||
<para>
|
||||
This is the official documentation of &repmgr; &repmgrversion; for
|
||||
use with PostgreSQL 9.4 - PostgreSQL 15.
|
||||
use with PostgreSQL 12 - PostgreSQL 17.
|
||||
</para>
|
||||
<para>
|
||||
&repmgr; is being continually developed and we strongly recommend using the
|
||||
|
||||
2
repmgr--5.4--5.5.sql
Normal file
2
repmgr--5.4--5.5.sql
Normal file
@@ -0,0 +1,2 @@
|
||||
-- complain if script is sourced in psql, rather than via CREAT EXTENSION
|
||||
\echo Use "CREATE EXTENSION repmgr" to load this file. \quit
|
||||
191
repmgr--5.5.sql
Normal file
191
repmgr--5.5.sql
Normal file
@@ -0,0 +1,191 @@
|
||||
-- complain if script is sourced in psql, rather than via CREATE EXTENSION
|
||||
\echo Use "CREATE EXTENSION repmgr" to load this file. \quit
|
||||
|
||||
CREATE TABLE repmgr.nodes (
|
||||
node_id INTEGER PRIMARY KEY,
|
||||
upstream_node_id INTEGER NULL REFERENCES nodes (node_id) DEFERRABLE,
|
||||
active BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
node_name TEXT NOT NULL,
|
||||
type TEXT NOT NULL CHECK (type IN('primary','standby','witness','bdr')),
|
||||
location TEXT NOT NULL DEFAULT 'default',
|
||||
priority INT NOT NULL DEFAULT 100,
|
||||
conninfo TEXT NOT NULL,
|
||||
repluser VARCHAR(63) NOT NULL,
|
||||
slot_name TEXT NULL,
|
||||
config_file TEXT NOT NULL
|
||||
);
|
||||
|
||||
SELECT pg_catalog.pg_extension_config_dump('repmgr.nodes', '');
|
||||
|
||||
CREATE TABLE repmgr.events (
|
||||
node_id INTEGER NOT NULL,
|
||||
event TEXT NOT NULL,
|
||||
successful BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
event_timestamp TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
details TEXT NULL
|
||||
);
|
||||
|
||||
SELECT pg_catalog.pg_extension_config_dump('repmgr.events', '');
|
||||
|
||||
CREATE TABLE repmgr.monitoring_history (
|
||||
primary_node_id INTEGER NOT NULL,
|
||||
standby_node_id INTEGER NOT NULL,
|
||||
last_monitor_time TIMESTAMP WITH TIME ZONE NOT NULL,
|
||||
last_apply_time TIMESTAMP WITH TIME ZONE,
|
||||
last_wal_primary_location PG_LSN NOT NULL,
|
||||
last_wal_standby_location PG_LSN,
|
||||
replication_lag BIGINT NOT NULL,
|
||||
apply_lag BIGINT NOT NULL
|
||||
);
|
||||
|
||||
CREATE INDEX idx_monitoring_history_time
|
||||
ON repmgr.monitoring_history (last_monitor_time, standby_node_id);
|
||||
|
||||
SELECT pg_catalog.pg_extension_config_dump('repmgr.monitoring_history', '');
|
||||
|
||||
CREATE VIEW repmgr.show_nodes AS
|
||||
SELECT n.node_id,
|
||||
n.node_name,
|
||||
n.active,
|
||||
n.upstream_node_id,
|
||||
un.node_name AS upstream_node_name,
|
||||
n.type,
|
||||
n.priority,
|
||||
n.conninfo
|
||||
FROM repmgr.nodes n
|
||||
LEFT JOIN repmgr.nodes un
|
||||
ON un.node_id = n.upstream_node_id;
|
||||
|
||||
CREATE TABLE repmgr.voting_term (
|
||||
term INT NOT NULL
|
||||
);
|
||||
|
||||
CREATE UNIQUE INDEX voting_term_restrict
|
||||
ON repmgr.voting_term ((TRUE));
|
||||
|
||||
CREATE RULE voting_term_delete AS
|
||||
ON DELETE TO repmgr.voting_term
|
||||
DO INSTEAD NOTHING;
|
||||
|
||||
|
||||
/* ================= */
|
||||
/* repmgrd functions */
|
||||
/* ================= */
|
||||
|
||||
/* monitoring functions */
|
||||
|
||||
CREATE FUNCTION set_local_node_id(INT)
|
||||
RETURNS VOID
|
||||
AS 'MODULE_PATHNAME', 'repmgr_set_local_node_id'
|
||||
LANGUAGE C STRICT;
|
||||
|
||||
CREATE FUNCTION get_local_node_id()
|
||||
RETURNS INT
|
||||
AS 'MODULE_PATHNAME', 'repmgr_get_local_node_id'
|
||||
LANGUAGE C STRICT;
|
||||
|
||||
CREATE FUNCTION standby_set_last_updated()
|
||||
RETURNS TIMESTAMP WITH TIME ZONE
|
||||
AS 'MODULE_PATHNAME', 'repmgr_standby_set_last_updated'
|
||||
LANGUAGE C STRICT;
|
||||
|
||||
CREATE FUNCTION standby_get_last_updated()
|
||||
RETURNS TIMESTAMP WITH TIME ZONE
|
||||
AS 'MODULE_PATHNAME', 'repmgr_standby_get_last_updated'
|
||||
LANGUAGE C STRICT;
|
||||
|
||||
CREATE FUNCTION set_upstream_last_seen(INT)
|
||||
RETURNS VOID
|
||||
AS 'MODULE_PATHNAME', 'repmgr_set_upstream_last_seen'
|
||||
LANGUAGE C STRICT;
|
||||
|
||||
CREATE FUNCTION get_upstream_last_seen()
|
||||
RETURNS INT
|
||||
AS 'MODULE_PATHNAME', 'repmgr_get_upstream_last_seen'
|
||||
LANGUAGE C STRICT;
|
||||
|
||||
CREATE FUNCTION get_upstream_node_id()
|
||||
RETURNS INT
|
||||
AS 'MODULE_PATHNAME', 'repmgr_get_upstream_node_id'
|
||||
LANGUAGE C STRICT;
|
||||
|
||||
CREATE FUNCTION set_upstream_node_id(INT)
|
||||
RETURNS VOID
|
||||
AS 'MODULE_PATHNAME', 'repmgr_set_upstream_node_id'
|
||||
LANGUAGE C STRICT;
|
||||
|
||||
/* failover functions */
|
||||
|
||||
CREATE FUNCTION notify_follow_primary(INT)
|
||||
RETURNS VOID
|
||||
AS 'MODULE_PATHNAME', 'repmgr_notify_follow_primary'
|
||||
LANGUAGE C STRICT;
|
||||
|
||||
CREATE FUNCTION get_new_primary()
|
||||
RETURNS INT
|
||||
AS 'MODULE_PATHNAME', 'repmgr_get_new_primary'
|
||||
LANGUAGE C STRICT;
|
||||
|
||||
CREATE FUNCTION reset_voting_status()
|
||||
RETURNS VOID
|
||||
AS 'MODULE_PATHNAME', 'repmgr_reset_voting_status'
|
||||
LANGUAGE C STRICT;
|
||||
|
||||
CREATE FUNCTION get_repmgrd_pid()
|
||||
RETURNS INT
|
||||
AS 'MODULE_PATHNAME', 'get_repmgrd_pid'
|
||||
LANGUAGE C STRICT;
|
||||
|
||||
CREATE FUNCTION get_repmgrd_pidfile()
|
||||
RETURNS TEXT
|
||||
AS 'MODULE_PATHNAME', 'get_repmgrd_pidfile'
|
||||
LANGUAGE C STRICT;
|
||||
|
||||
CREATE FUNCTION set_repmgrd_pid(INT, TEXT)
|
||||
RETURNS VOID
|
||||
AS 'MODULE_PATHNAME', 'set_repmgrd_pid'
|
||||
LANGUAGE C CALLED ON NULL INPUT;
|
||||
|
||||
CREATE FUNCTION repmgrd_is_running()
|
||||
RETURNS BOOL
|
||||
AS 'MODULE_PATHNAME', 'repmgrd_is_running'
|
||||
LANGUAGE C STRICT;
|
||||
|
||||
CREATE FUNCTION repmgrd_pause(BOOL)
|
||||
RETURNS VOID
|
||||
AS 'MODULE_PATHNAME', 'repmgrd_pause'
|
||||
LANGUAGE C STRICT;
|
||||
|
||||
CREATE FUNCTION repmgrd_is_paused()
|
||||
RETURNS BOOL
|
||||
AS 'MODULE_PATHNAME', 'repmgrd_is_paused'
|
||||
LANGUAGE C STRICT;
|
||||
|
||||
CREATE FUNCTION get_wal_receiver_pid()
|
||||
RETURNS INT
|
||||
AS 'MODULE_PATHNAME', 'repmgr_get_wal_receiver_pid'
|
||||
LANGUAGE C STRICT;
|
||||
|
||||
|
||||
|
||||
|
||||
/* views */
|
||||
|
||||
CREATE VIEW repmgr.replication_status AS
|
||||
SELECT m.primary_node_id, m.standby_node_id, n.node_name AS standby_name,
|
||||
n.type AS node_type, n.active, last_monitor_time,
|
||||
CASE WHEN n.type='standby' THEN m.last_wal_primary_location ELSE NULL END AS last_wal_primary_location,
|
||||
m.last_wal_standby_location,
|
||||
CASE WHEN n.type='standby' THEN pg_catalog.pg_size_pretty(m.replication_lag) ELSE NULL END AS replication_lag,
|
||||
CASE WHEN n.type='standby' THEN
|
||||
CASE WHEN replication_lag > 0 THEN age(now(), m.last_apply_time) ELSE '0'::INTERVAL END
|
||||
ELSE NULL
|
||||
END AS replication_time_lag,
|
||||
CASE WHEN n.type='standby' THEN pg_catalog.pg_size_pretty(m.apply_lag) ELSE NULL END AS apply_lag,
|
||||
AGE(NOW(), CASE WHEN pg_catalog.pg_is_in_recovery() THEN repmgr.standby_get_last_updated() ELSE m.last_monitor_time END) AS communication_time_lag
|
||||
FROM repmgr.monitoring_history m
|
||||
JOIN repmgr.nodes n ON m.standby_node_id = n.node_id
|
||||
WHERE (m.standby_node_id, m.last_monitor_time) IN (
|
||||
SELECT m1.standby_node_id, MAX(m1.last_monitor_time)
|
||||
FROM repmgr.monitoring_history m1 GROUP BY 1
|
||||
);
|
||||
@@ -394,7 +394,6 @@ do_node_status(void)
|
||||
if (node_info.inactive_replication_slots > 0)
|
||||
{
|
||||
KeyValueList inactive_replication_slots = {NULL, NULL};
|
||||
KeyValueListCell *cell = NULL;
|
||||
|
||||
(void) get_inactive_replication_slots(conn, &inactive_replication_slots);
|
||||
|
||||
@@ -524,8 +523,6 @@ do_node_status(void)
|
||||
if (node_info.inactive_replication_slots)
|
||||
{
|
||||
KeyValueList inactive_replication_slots = {NULL, NULL};
|
||||
KeyValueListCell *cell = NULL;
|
||||
|
||||
(void) get_inactive_replication_slots(conn, &inactive_replication_slots);
|
||||
for (cell = inactive_replication_slots.head; cell; cell = cell->next)
|
||||
{
|
||||
@@ -2365,18 +2362,25 @@ do_node_service(void)
|
||||
conn = establish_db_connection_by_params(&source_conninfo, true);
|
||||
}
|
||||
|
||||
if (is_superuser_connection(conn, NULL) == false)
|
||||
if (can_execute_checkpoint(conn) == false)
|
||||
{
|
||||
if (runtime_options.dry_run == true)
|
||||
{
|
||||
log_warning(_("a CHECKPOINT would be issued here but no superuser connection is available"));
|
||||
log_warning(_("a CHECKPOINT would be issued here but no authorized connection is available"));
|
||||
}
|
||||
else
|
||||
{
|
||||
log_warning(_("a superuser connection is required to issue a CHECKPOINT"));
|
||||
log_warning(_("an authorized connection is required to issue a CHECKPOINT"));
|
||||
}
|
||||
|
||||
log_hint(_("provide a superuser with -S/--superuser"));
|
||||
if (PQserverVersion(conn) >= 150000)
|
||||
{
|
||||
log_hint(_("provide a superuser with -S/--superuser or grant pg_checkpoint role to repmgr user"));
|
||||
}
|
||||
else
|
||||
{
|
||||
log_hint(_("provide a superuser with -S/--superuser"));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2539,6 +2543,7 @@ do_node_rejoin(void)
|
||||
int server_version_num = UNKNOWN_SERVER_VERSION_NUM;
|
||||
bool hide_standby_signal = false;
|
||||
|
||||
KeyValueListCell *cell = NULL;
|
||||
PQExpBufferData command;
|
||||
PQExpBufferData command_output;
|
||||
PQExpBufferData follow_output;
|
||||
@@ -2958,7 +2963,7 @@ do_node_rejoin(void)
|
||||
else
|
||||
{
|
||||
while ((slotdir_ent = readdir(slotdir)) != NULL) {
|
||||
struct stat statbuf;
|
||||
struct stat local_statbuf;
|
||||
PQExpBufferData slotdir_ent_path;
|
||||
|
||||
if (strcmp(slotdir_ent->d_name, ".") == 0 || strcmp(slotdir_ent->d_name, "..") == 0)
|
||||
@@ -2971,7 +2976,7 @@ do_node_rejoin(void)
|
||||
slotdir_path.data,
|
||||
slotdir_ent->d_name);
|
||||
|
||||
if (stat(slotdir_ent_path.data, &statbuf) == 0 && !S_ISDIR(statbuf.st_mode))
|
||||
if (stat(slotdir_ent_path.data, &local_statbuf) == 0 && !S_ISDIR(local_statbuf.st_mode))
|
||||
{
|
||||
termPQExpBuffer(&slotdir_ent_path);
|
||||
continue;
|
||||
@@ -3102,7 +3107,6 @@ do_node_rejoin(void)
|
||||
else
|
||||
{
|
||||
KeyValueList inactive_replication_slots = {NULL, NULL};
|
||||
KeyValueListCell *cell = NULL;
|
||||
int inactive_count = 0;
|
||||
PQExpBufferData slotinfo;
|
||||
|
||||
|
||||
@@ -235,6 +235,38 @@ do_primary_register(void)
|
||||
return;
|
||||
}
|
||||
|
||||
static inline void reset_node_info(t_node_info *info)
|
||||
{
|
||||
info->node_id = NODE_NOT_FOUND;
|
||||
info->upstream_node_id = NO_UPSTREAM_NODE;
|
||||
info->type = UNKNOWN;
|
||||
info->node_name[0] = '\0';
|
||||
info->upstream_node_name[0] = '\0';
|
||||
info->conninfo[0] = '\0';
|
||||
info->repluser[0] = '\0';
|
||||
info->priority = DEFAULT_PRIORITY;
|
||||
info->active = true;
|
||||
info->slot_name[0] = '\0';
|
||||
info->config_file[0] = '\0';
|
||||
info->last_wal_receive_lsn = InvalidXLogRecPtr;
|
||||
info->node_status = NODE_STATUS_UNKNOWN;
|
||||
info->recovery_type = RECTYPE_UNKNOWN;
|
||||
info->monitoring_state = MS_NORMAL;
|
||||
info->conn = NULL;
|
||||
info->details[0] = '\0';
|
||||
info->reachable = true;
|
||||
info->attached = true;
|
||||
/* various statistics */
|
||||
info->max_wal_senders = -1;
|
||||
info->attached_wal_receivers = -1;
|
||||
info->max_replication_slots = -1;
|
||||
info->total_replication_slots = -1;
|
||||
info->active_replication_slots = -1;
|
||||
info->inactive_replication_slots = -1;
|
||||
info->replication_info = NULL;
|
||||
|
||||
strlcpy(info->location, DEFAULT_LOCATION, sizeof(info->location));
|
||||
}
|
||||
|
||||
/*
|
||||
* do_primary_unregister()
|
||||
@@ -436,7 +468,7 @@ do_primary_unregister(void)
|
||||
}
|
||||
else if (recovery_type == RECTYPE_PRIMARY)
|
||||
{
|
||||
t_node_info primary_node_info = T_NODE_INFO_INITIALIZER;
|
||||
reset_node_info(&primary_node_info);
|
||||
bool primary_record_found = false;
|
||||
|
||||
primary_record_found = get_primary_node_record(primary_conn, &primary_node_info);
|
||||
|
||||
@@ -535,7 +535,7 @@ do_standby_clone(void)
|
||||
|
||||
if (external_config_files == true)
|
||||
{
|
||||
int r;
|
||||
r = 0;
|
||||
PQExpBufferData msg;
|
||||
|
||||
initPQExpBuffer(&msg);
|
||||
@@ -762,7 +762,7 @@ do_standby_clone(void)
|
||||
if (mode == pg_basebackup && runtime_options.verify_backup == true)
|
||||
{
|
||||
PQExpBufferData command;
|
||||
int r;
|
||||
r = 0;
|
||||
struct stat st;
|
||||
|
||||
initPQExpBuffer(&command);
|
||||
@@ -3927,7 +3927,6 @@ do_standby_switchover(void)
|
||||
|
||||
if (PQserverVersion(local_conn) < 130000 && is_wal_replay_paused(local_conn, false) == true)
|
||||
{
|
||||
ReplInfo replication_info;
|
||||
init_replication_info(&replication_info);
|
||||
|
||||
if (get_replication_info(local_conn, STANDBY, &replication_info) == false)
|
||||
@@ -4784,7 +4783,7 @@ do_standby_switchover(void)
|
||||
{
|
||||
NodeInfoListCell *cell = NULL;
|
||||
ItemList repmgrd_connection_errors = {NULL, NULL};
|
||||
int i = 0;
|
||||
i = 0;
|
||||
int unreachable_node_count = 0;
|
||||
|
||||
get_all_node_records(local_conn, &all_nodes);
|
||||
@@ -5099,8 +5098,6 @@ do_standby_switchover(void)
|
||||
/* database server could not be contacted */
|
||||
if (ping_res == PQPING_NO_RESPONSE || ping_res == PQPING_NO_ATTEMPT)
|
||||
{
|
||||
bool command_success;
|
||||
|
||||
/*
|
||||
* remote server can't be contacted at protocol level - that
|
||||
* doesn't necessarily mean it's shut down, so we'll ask its
|
||||
@@ -5288,7 +5285,7 @@ do_standby_switchover(void)
|
||||
checkpoint_conn = superuser_conn;
|
||||
}
|
||||
|
||||
if (is_superuser_connection(checkpoint_conn, NULL) == true)
|
||||
if (can_execute_checkpoint(checkpoint_conn) == true)
|
||||
{
|
||||
log_notice(_("issuing CHECKPOINT on node \"%s\" (ID: %i) "),
|
||||
config_file_options.node_name,
|
||||
@@ -5297,7 +5294,16 @@ do_standby_switchover(void)
|
||||
}
|
||||
else
|
||||
{
|
||||
log_warning(_("no superuser connection available, unable to issue CHECKPOINT"));
|
||||
log_warning(_("no authorized connection available, unable to issue CHECKPOINT"));
|
||||
|
||||
if (PQserverVersion(local_conn) >= 150000)
|
||||
{
|
||||
log_hint(_("provide a superuser with -S/--superuser or grant pg_checkpoint role to repmgr user"));
|
||||
}
|
||||
else
|
||||
{
|
||||
log_hint(_("provide a superuser with -S/--superuser"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5669,7 +5675,7 @@ do_standby_switchover(void)
|
||||
{
|
||||
ItemList repmgrd_unpause_errors = {NULL, NULL};
|
||||
NodeInfoListCell *cell = NULL;
|
||||
int i = 0;
|
||||
i = 0;
|
||||
int error_node_count = 0;
|
||||
|
||||
for (cell = all_nodes.head; cell; cell = cell->next)
|
||||
@@ -6504,12 +6510,12 @@ check_upstream_config(PGconn *conn, int server_version_num, t_node_info *upstrea
|
||||
if (mode == pg_basebackup)
|
||||
{
|
||||
|
||||
PGconn **connections;
|
||||
int i;
|
||||
int available_wal_senders;
|
||||
int min_replication_connections = 1;
|
||||
int possible_replication_connections = 0;
|
||||
t_conninfo_param_list repl_conninfo = T_CONNINFO_PARAM_LIST_INITIALIZER;
|
||||
PGconn **connections;
|
||||
int available_wal_senders;
|
||||
int min_replication_connections = 1;
|
||||
int possible_replication_connections = 0;
|
||||
i = 0;
|
||||
t_conninfo_param_list repl_conninfo = T_CONNINFO_PARAM_LIST_INITIALIZER;
|
||||
|
||||
|
||||
/*
|
||||
@@ -8471,7 +8477,6 @@ check_sibling_nodes(NodeInfoList *sibling_nodes, SiblingNodeStats *sibling_nodes
|
||||
if (sibling_nodes->node_count > 0)
|
||||
{
|
||||
PQExpBufferData nodes;
|
||||
NodeInfoListCell *cell;
|
||||
|
||||
initPQExpBuffer(&nodes);
|
||||
|
||||
|
||||
@@ -70,7 +70,11 @@
|
||||
#include "repmgr-action-service.h"
|
||||
#include "repmgr-action-daemon.h"
|
||||
|
||||
#if (PG_VERSION_NUM >= 170000)
|
||||
#include <common/file_utils.h> /* for PG_TEMP_FILE_PREFIX */
|
||||
#else
|
||||
#include <storage/fd.h> /* for PG_TEMP_FILE_PREFIX */
|
||||
#endif
|
||||
|
||||
/* globally available variables *
|
||||
* ============================ */
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
#
|
||||
# For details on the configuration file format see the documentation at:
|
||||
#
|
||||
# https://repmgr.org/docs/current/configuration-file.html#CONFIGURATION-FILE-FORMAT
|
||||
# https://repmgr.org/docs/current/configuration-file.html#CONFIGURATION-FILE-FORMAT
|
||||
#
|
||||
# =============================================================================
|
||||
# Required configuration items
|
||||
@@ -76,7 +76,7 @@
|
||||
#location='default' # An arbitrary string defining the location of the node; this
|
||||
# is used during failover to check visibility of the
|
||||
# current primary node. For further details see:
|
||||
# https://repmgr.org/docs/current/repmgrd-network-split.html
|
||||
# https://repmgr.org/docs/current/repmgrd-network-split.html
|
||||
|
||||
#use_replication_slots=no # whether to use physical replication slots
|
||||
# NOTE: when using replication slots,
|
||||
@@ -181,8 +181,8 @@
|
||||
|
||||
#pg_ctl_options='' # Options to append to "pg_ctl"
|
||||
#pg_basebackup_options='' # Options to append to "pg_basebackup"
|
||||
# (Note: when cloning from Barman, repmgr will honour any
|
||||
# --waldir/--xlogdir setting present in "pg_basebackup_options"
|
||||
# (Note: when cloning from Barman, repmgr will honour any
|
||||
# --waldir/--xlogdir setting present in "pg_basebackup_options"
|
||||
#rsync_options='' # Options to append to "rsync"
|
||||
ssh_options='-q -o ConnectTimeout=10' # Options to append to "ssh"
|
||||
|
||||
@@ -212,8 +212,8 @@ ssh_options='-q -o ConnectTimeout=10' # Options to append to "ssh"
|
||||
|
||||
#recovery_min_apply_delay= # If provided, "recovery_min_apply_delay" will be set to
|
||||
# this value (PostgreSQL 9.4 and later). Value can be
|
||||
# an integer representing milliseconds, or a string
|
||||
# representing a period of time (e.g. '5 min').
|
||||
# an integer representing milliseconds, or a string
|
||||
# representing a period of time (e.g. '5 min').
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
@@ -299,7 +299,7 @@ ssh_options='-q -o ConnectTimeout=10' # Options to append to "ssh"
|
||||
# a value of zero prevents the node being promoted to primary
|
||||
# (default: 100)
|
||||
|
||||
#connection_check_type=ping # How to check availability of the upstream node; valid options:
|
||||
#connection_check_type='ping' # How to check availability of the upstream node; valid options:
|
||||
# 'ping': use PQping() to check if the node is accepting connections
|
||||
# 'connection': attempt to make a new connection to the node
|
||||
# 'query': execute an SQL statement on the node via the existing connection
|
||||
@@ -344,20 +344,27 @@ ssh_options='-q -o ConnectTimeout=10' # Options to append to "ssh"
|
||||
# From PostgreSQL 15 repmgr must be a superuser or have 'ALTER SYSTEM wal_retrieve_retry_interval' privilege.
|
||||
# (see: https://repmgr.org/docs/current/repmgrd-standby-disconnection-on-failover.html )
|
||||
#sibling_nodes_disconnect_timeout=30 # If "standby_disconnect_on_failover" is true, the maximum length of time
|
||||
# (in seconds) to wait for other standbys to confirm they have disconnected their
|
||||
# (in seconds) to wait for other standbys to confirm they have disconnected their
|
||||
# WAL receivers
|
||||
#primary_visibility_consensus=false # If "true", only continue with failover if no standbys have seen
|
||||
# the primary node recently. *Must* be the same on all nodes.
|
||||
#always_promote=false # Always promote a node, even if repmgr metadata is outdated
|
||||
#failover_validation_command='' # Script to execute for an external mechanism to validate the failover
|
||||
# decision made by repmgrd. One or both of the following parameter placeholders
|
||||
# should be provided, which will be replaced by repmgrd with the appropriate
|
||||
# value: %n (node_id), %a (node_name). *Must* be the same on all nodes.
|
||||
#failover_validation_command='' # Script to execute for an external mechanism to validate the failover
|
||||
# decision made by repmgrd. Each of the following parameter placeholders
|
||||
# should be provided, which will be replaced by repmgrd with the appropriate value:
|
||||
# %n (node_id)
|
||||
# %a (node_name)
|
||||
# %v (number of visible nodes)
|
||||
# %u (number of shared upstream nodes)
|
||||
# %t (total number of nodes)
|
||||
# *Must* be the same on all nodes.
|
||||
#election_rerun_interval=15 # if "failover_validation_command" is set, and the command returns
|
||||
# an error, pause the specified amount of seconds before rerunning the election.
|
||||
#
|
||||
# The following items are relevant for repmgrd running on the primary,
|
||||
# and will be ignored on non-primary nodes
|
||||
|
||||
# The following items are relevant for repmgrd running on the primary,
|
||||
# and will be ignored on non-primary nodes.
|
||||
# (see: https://repmgr.org/docs/current/repmgrd-primary-child-disconnection.html )
|
||||
|
||||
#child_nodes_check_interval=5 # Interval (in seconds) to check for attached child nodes (standbys)
|
||||
#child_nodes_connected_min_count=-1 # Minimum number of child nodes which must remain connected, otherwise
|
||||
# disconnection command will be triggered
|
||||
@@ -365,6 +372,7 @@ ssh_options='-q -o ConnectTimeout=10' # Options to append to "ssh"
|
||||
# (ignored if "child_nodes_connected_min_count" set)
|
||||
#child_nodes_disconnect_timeout=30 # Interval between child node disconnection and disconnection command execution
|
||||
#child_nodes_disconnect_command='' # Command to execute if child node disconnection detected
|
||||
#child_nodes_connected_include_witness=false # Whether to count the witness node (if in use) as a child node when determining whether to execute child_nodes_disconnect_command.
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# service control commands
|
||||
@@ -387,20 +395,20 @@ ssh_options='-q -o ConnectTimeout=10' # Options to append to "ssh"
|
||||
#
|
||||
# For example, to use systemd, you can set
|
||||
#
|
||||
# service_start_command = 'sudo systemctl start postgresql-9.6'
|
||||
# service_start_command = 'sudo systemctl start postgresql-16'
|
||||
# (...)
|
||||
#
|
||||
# and then use the following sudoers configuration:
|
||||
#
|
||||
# # this is required when running sudo over ssh without -t:
|
||||
# Defaults:postgres !requiretty
|
||||
# postgres ALL = NOPASSWD: /usr/bin/systemctl stop postgresql-9.6, \
|
||||
# /usr/bin/systemctl start postgresql-9.6, \
|
||||
# /usr/bin/systemctl restart postgresql-9.6
|
||||
# postgres ALL = NOPASSWD: /usr/bin/systemctl stop postgresql-16, \
|
||||
# /usr/bin/systemctl start postgresql-16, \
|
||||
# /usr/bin/systemctl restart postgresql-16
|
||||
#
|
||||
# Debian/Ubuntu users: use "sudo pg_ctlcluster" to execute service control commands.
|
||||
#
|
||||
# For more details, see: https://repmgr.org/docs/current/configuration-file-service-commands.html
|
||||
# For further details, see: https://repmgr.org/docs/current/configuration-file-service-commands.html
|
||||
|
||||
#service_start_command = ''
|
||||
#service_stop_command = ''
|
||||
@@ -443,4 +451,3 @@ ssh_options='-q -o ConnectTimeout=10' # Options to append to "ssh"
|
||||
# "repmgr standby switchover" to warn about potential
|
||||
# issues with shutting down the demotion candidate.
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# repmgr extension
|
||||
comment = 'Replication manager for PostgreSQL'
|
||||
default_version = '5.4'
|
||||
default_version = '5.5'
|
||||
module_pathname = '$libdir/repmgr'
|
||||
relocatable = false
|
||||
schema = repmgr
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#define REPMGR_VERSION_DATE ""
|
||||
#define REPMGR_VERSION "5.4dev"
|
||||
#define REPMGR_VERSION_NUM 50400
|
||||
#define REPMGR_EXTENSION_VERSION "5.4"
|
||||
#define REPMGR_EXTENSION_NUM 50400
|
||||
#define REPMGR_RELEASE_DATE "2022-XX-XX"
|
||||
#define REPMGR_VERSION_DATE "2024-11-20"
|
||||
#define REPMGR_VERSION "5.5.0"
|
||||
#define REPMGR_VERSION_NUM 50500
|
||||
#define REPMGR_EXTENSION_VERSION "5.5.0"
|
||||
#define REPMGR_EXTENSION_NUM 50500
|
||||
#define REPMGR_RELEASE_DATE "2024-XX-XX"
|
||||
#define PG_ACTUAL_VERSION_NUM
|
||||
|
||||
@@ -1359,6 +1359,8 @@ monitor_streaming_standby(void)
|
||||
MonitoringState local_monitoring_state = MS_NORMAL;
|
||||
instr_time local_degraded_monitoring_start;
|
||||
|
||||
bool upstream_check_result;
|
||||
int degraded_monitoring_elapsed;
|
||||
int last_known_upstream_node_id = UNKNOWN_NODE_ID;
|
||||
|
||||
log_debug("monitor_streaming_standby()");
|
||||
@@ -1547,7 +1549,6 @@ monitor_streaming_standby(void)
|
||||
|
||||
while (true)
|
||||
{
|
||||
bool upstream_check_result;
|
||||
|
||||
log_verbose(LOG_DEBUG, "checking %s", upstream_node_info.conninfo);
|
||||
|
||||
@@ -1770,8 +1771,7 @@ monitor_streaming_standby(void)
|
||||
|
||||
if (monitoring_state == MS_DEGRADED)
|
||||
{
|
||||
int degraded_monitoring_elapsed = calculate_elapsed(degraded_monitoring_start);
|
||||
bool upstream_check_result;
|
||||
degraded_monitoring_elapsed = calculate_elapsed(degraded_monitoring_start);
|
||||
|
||||
if (config_file_options.degraded_monitoring_timeout > 0
|
||||
&& degraded_monitoring_elapsed > config_file_options.degraded_monitoring_timeout)
|
||||
@@ -1894,7 +1894,6 @@ monitor_streaming_standby(void)
|
||||
*/
|
||||
if (failover_state == FAILOVER_STATE_PROMOTION_FAILED)
|
||||
{
|
||||
int degraded_monitoring_elapsed;
|
||||
int former_upstream_node_id = local_node_info.upstream_node_id;
|
||||
NodeInfoList sibling_nodes = T_NODE_INFO_LIST_INITIALIZER;
|
||||
PQExpBufferData event_details;
|
||||
@@ -1953,7 +1952,7 @@ monitor_streaming_standby(void)
|
||||
|
||||
if (local_node_info.type == PRIMARY)
|
||||
{
|
||||
int degraded_monitoring_elapsed = calculate_elapsed(degraded_monitoring_start);
|
||||
degraded_monitoring_elapsed = calculate_elapsed(degraded_monitoring_start);
|
||||
|
||||
log_notice(_("resuming monitoring as primary node after %i seconds"),
|
||||
degraded_monitoring_elapsed);
|
||||
|
||||
Reference in New Issue
Block a user