mirror of
https://github.com/EnterpriseDB/repmgr.git
synced 2026-03-25 08:06:29 +00:00
Merge branch 'docs'
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -40,6 +40,8 @@ lib*.pc
|
|||||||
# test output
|
# test output
|
||||||
/results/
|
/results/
|
||||||
|
|
||||||
|
/doc/Makefile
|
||||||
|
|
||||||
# other
|
# other
|
||||||
/.lineno
|
/.lineno
|
||||||
*.dSYM
|
*.dSYM
|
||||||
|
|||||||
@@ -63,6 +63,12 @@ Makefile: Makefile.in config.status configure
|
|||||||
Makefile.global: Makefile.global.in config.status configure
|
Makefile.global: Makefile.global.in config.status configure
|
||||||
./config.status $@
|
./config.status $@
|
||||||
|
|
||||||
|
doc:
|
||||||
|
$(MAKE) -C doc all
|
||||||
|
|
||||||
|
install-doc:
|
||||||
|
$(MAKE) -C doc install
|
||||||
|
|
||||||
clean: additional-clean
|
clean: additional-clean
|
||||||
|
|
||||||
maintainer-clean: additional-maintainer-clean
|
maintainer-clean: additional-maintainer-clean
|
||||||
|
|||||||
@@ -991,10 +991,10 @@ active primary, the previous warning will not be displayed:
|
|||||||
|
|
||||||
$ repmgr -f /etc/repmgr.conf cluster show
|
$ repmgr -f /etc/repmgr.conf cluster show
|
||||||
ID | Name | Role | Status | Upstream | Location | Connection string
|
ID | Name | Role | Status | Upstream | Location | Connection string
|
||||||
----+-------+---------+-----------+----------+----------+----------------------------------------------------
|
----+-------+---------+-----------+----------+----------+--------------------------------------
|
||||||
1 | node1 | primary | - failed | | default | host=node1 dbname=repmgr user=repmgr port=5501
|
1 | node1 | primary | - failed | | default | host=node1 dbname=repmgr user=repmgr
|
||||||
2 | node2 | primary | * running | | default | host=node2 dbname=repmgr user=repmgr port=5502
|
2 | node2 | primary | * running | | default | host=node2 dbname=repmgr user=repmgr
|
||||||
3 | node3 | standby | running | node1 | default | host=node3 dbname=repmgr user=repmgr port=5503
|
3 | node3 | standby | running | node1 | default | host=node3 dbname=repmgr user=repmgr
|
||||||
|
|
||||||
However the sole remaining standby is still trying to replicate from the failed
|
However the sole remaining standby is still trying to replicate from the failed
|
||||||
primary; `repmgr standby follow` must now be executed to rectify this situation.
|
primary; `repmgr standby follow` must now be executed to rectify this situation.
|
||||||
|
|||||||
3
configure
vendored
3
configure
vendored
@@ -1871,6 +1871,8 @@ ac_config_files="$ac_config_files Makefile"
|
|||||||
|
|
||||||
ac_config_files="$ac_config_files Makefile.global"
|
ac_config_files="$ac_config_files Makefile.global"
|
||||||
|
|
||||||
|
ac_config_files="$ac_config_files doc/Makefile"
|
||||||
|
|
||||||
cat >confcache <<\_ACEOF
|
cat >confcache <<\_ACEOF
|
||||||
# This file is a shell script that caches the results of configure
|
# This file is a shell script that caches the results of configure
|
||||||
# tests run on this system so they can be shared between configure
|
# tests run on this system so they can be shared between configure
|
||||||
@@ -2564,6 +2566,7 @@ do
|
|||||||
"config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
|
"config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
|
||||||
"Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
|
"Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
|
||||||
"Makefile.global") CONFIG_FILES="$CONFIG_FILES Makefile.global" ;;
|
"Makefile.global") CONFIG_FILES="$CONFIG_FILES Makefile.global" ;;
|
||||||
|
"doc/Makefile") CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;;
|
||||||
|
|
||||||
*) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
|
*) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
|
||||||
esac
|
esac
|
||||||
|
|||||||
@@ -65,5 +65,6 @@ AC_SUBST(vpath_build)
|
|||||||
|
|
||||||
AC_CONFIG_FILES([Makefile])
|
AC_CONFIG_FILES([Makefile])
|
||||||
AC_CONFIG_FILES([Makefile.global])
|
AC_CONFIG_FILES([Makefile.global])
|
||||||
|
AC_CONFIG_FILES([doc/Makefile])
|
||||||
AC_OUTPUT
|
AC_OUTPUT
|
||||||
|
|
||||||
|
|||||||
5
doc/.gitignore
vendored
Normal file
5
doc/.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
HTML.index
|
||||||
|
bookindex.sgml
|
||||||
|
html-stamp
|
||||||
|
html/
|
||||||
|
version.sgml
|
||||||
71
doc/Makefile.in
Normal file
71
doc/Makefile.in
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
repmgr_subdir = doc
|
||||||
|
repmgr_top_builddir = ..
|
||||||
|
include $(repmgr_top_builddir)/Makefile.global
|
||||||
|
|
||||||
|
ifndef JADE
|
||||||
|
JADE = $(missing) jade
|
||||||
|
endif
|
||||||
|
|
||||||
|
SGMLINCLUDE = -D . -D ${srcdir}
|
||||||
|
|
||||||
|
SPFLAGS += -wall -wno-unused-param -wno-empty -wfully-tagged
|
||||||
|
|
||||||
|
JADE.html.call = $(JADE) $(JADEFLAGS) $(SPFLAGS) $(SGMLINCLUDE) $(CATALOG) -d stylesheet.dsl -t sgml -i output-html
|
||||||
|
|
||||||
|
ALLSGML := $(wildcard $(srcdir)/*.sgml)
|
||||||
|
# to build bookindex
|
||||||
|
ALMOSTALLSGML := $(filter-out %bookindex.sgml,$(ALLSGML))
|
||||||
|
GENERATED_SGML = version.sgml bookindex.sgml
|
||||||
|
|
||||||
|
Makefile: Makefile.in
|
||||||
|
cd $(repmgr_top_builddir) && ./config.status doc/Makefile
|
||||||
|
|
||||||
|
all: html
|
||||||
|
|
||||||
|
html: html-stamp
|
||||||
|
|
||||||
|
html-stamp: repmgr.sgml $(ALLSGML) $(GENERATED_SGML) stylesheet.dsl website-docs.css
|
||||||
|
$(MKDIR_P) html
|
||||||
|
$(JADE.html.call) -i include-index $<
|
||||||
|
cp $(srcdir)/stylesheet.css $(srcdir)/website-docs.css html/
|
||||||
|
touch $@
|
||||||
|
|
||||||
|
version.sgml: ${repmgr_top_builddir}/repmgr_version.h
|
||||||
|
{ \
|
||||||
|
echo "<!ENTITY repmgrversion \"$(REPMGR_VERSION)\">"; \
|
||||||
|
} > $@
|
||||||
|
|
||||||
|
HTML.index: repmgr.sgml $(ALMOSTALLSGML) stylesheet.dsl
|
||||||
|
@$(MKDIR_P) html
|
||||||
|
$(JADE.html.call) -V html-index $<
|
||||||
|
|
||||||
|
website-docs.css:
|
||||||
|
@$(MKDIR_P) html
|
||||||
|
curl http://www.postgresql.org/media/css/docs.css > ${srcdir}/website-docs.css
|
||||||
|
|
||||||
|
bookindex.sgml: HTML.index
|
||||||
|
ifdef COLLATEINDEX
|
||||||
|
LC_ALL=C $(PERL) $(COLLATEINDEX) -f -g -i 'bookindex' -o $@ $<
|
||||||
|
else
|
||||||
|
@$(missing) collateindex.pl $< $@
|
||||||
|
endif
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f html-stamp
|
||||||
|
rm -f HTML.index $(GENERATED_SGML)
|
||||||
|
|
||||||
|
maintainer-clean:
|
||||||
|
rm -rf html
|
||||||
|
rm -rf Makefile
|
||||||
|
|
||||||
|
zip: html
|
||||||
|
cp -r html repmgr-docs-$(REPMGR_VERSION)
|
||||||
|
zip -r repmgr-docs-$(REPMGR_VERSION).zip repmgr-docs-$(REPMGR_VERSION)
|
||||||
|
rm -rf repmgr-docs-$(REPMGR_VERSION)
|
||||||
|
|
||||||
|
install: html
|
||||||
|
@$(MKDIR_P) $(DESTDIR)$(docdir)/$(docmoduledir)/repmgr
|
||||||
|
@$(INSTALL_DATA) $(wildcard html/*.html) $(wildcard html/*.css) $(DESTDIR)$(docdir)/$(docmoduledir)/repmgr
|
||||||
|
@echo Installed docs to $(DESTDIR)$(docdir)/$(docmoduledir)/repmgr
|
||||||
|
|
||||||
|
.PHONY: html all
|
||||||
5
doc/appendix-signatures.sgml
Normal file
5
doc/appendix-signatures.sgml
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<appendix id="appendix-signatures" xreflabel="Verifying digital signatures">
|
||||||
|
<title>Verifying digital signatures</title>
|
||||||
|
|
||||||
|
<para>WIP</para>
|
||||||
|
</appendix>
|
||||||
403
doc/cloning-standbys.sgml
Normal file
403
doc/cloning-standbys.sgml
Normal file
@@ -0,0 +1,403 @@
|
|||||||
|
<chapter id="cloning-standbys" xreflabel="cloning standbys">
|
||||||
|
<title>Cloning standbys</title>
|
||||||
|
<para>
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<sect1 id="cloning-from-barman" xreflabel="Cloning from Barman">
|
||||||
|
<indexterm>
|
||||||
|
<primary>cloning</primary>
|
||||||
|
<secondary>from Barman</secondary>
|
||||||
|
</indexterm>
|
||||||
|
<title>Cloning a standby from Barman</title>
|
||||||
|
<para>
|
||||||
|
<xref linkend="repmgr-standby-clone"> can use
|
||||||
|
<ulink url="https://www.2ndquadrant.com/">2ndQuadrant</ulink>'s
|
||||||
|
<ulink url="https://www.pgbarman.org/">Barman</ulink> application
|
||||||
|
to clone a standby (and also as a fallback source for WAL files).
|
||||||
|
</para>
|
||||||
|
<tip>
|
||||||
|
<simpara>
|
||||||
|
Barman (aka PgBarman) should be considered as an integral part of any
|
||||||
|
PostgreSQL replication cluster. For more details see:
|
||||||
|
<ulink url="https://www.pgbarman.org/">https://www.pgbarman.org/</ulink>.
|
||||||
|
</simpara>
|
||||||
|
</tip>
|
||||||
|
<para>
|
||||||
|
Barman support provides the following advantages:
|
||||||
|
<itemizedlist spacing="compact" mark="bullet">
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
the primary node does not need to perform a new backup every time a
|
||||||
|
new standby is cloned
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
a standby node can be disconnected for longer periods without losing
|
||||||
|
the ability to catch up, and without causing accumulation of WAL
|
||||||
|
files on the primary node
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
WAL management on the primary becomes much easier as there's no need
|
||||||
|
to use replication slots, and <varname>wal_keep_segments</varname>
|
||||||
|
does not need to be set.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<sect2 id="cloning-from-barman-prerequisites" xreflabel="Prerequisites for cloning from Barman">
|
||||||
|
<title>Prerequisites for cloning from Barman</title>
|
||||||
|
<para>
|
||||||
|
In order to enable Barman support for <command>repmgr standby clone</command>, following
|
||||||
|
prerequisites must be met:
|
||||||
|
<itemizedlist spacing="compact" mark="bullet">
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
the <varname>barman_server</varname> setting in <filename>repmgr.conf</filename> is the same as the
|
||||||
|
server configured in Barman;
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
the <varname>barman_host</varname> setting in <filename>repmgr.conf</filename> is set to the SSH
|
||||||
|
hostname of the Barman server;
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
the <varname>restore_command</varname> setting in <filename>repmgr.conf</filename> is configured to
|
||||||
|
use a copy of the <command>barman-wal-restore</command> script shipped with the
|
||||||
|
<literal>barman-cli</literal> package (see below);
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
the Barman catalogue includes at least one valid backup for this server.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
</para>
|
||||||
|
<note>
|
||||||
|
<simpara>
|
||||||
|
Barman support is automatically enabled if <varname>barman_server</varname>
|
||||||
|
is set. Normally it is good practice to use Barman, for instance
|
||||||
|
when fetching a base backup while cloning a standby; in any case,
|
||||||
|
Barman mode can be disabled using the <literal>--without-barman</literal>
|
||||||
|
command line option.
|
||||||
|
</simpara>
|
||||||
|
</note>
|
||||||
|
<tip>
|
||||||
|
<simpara>
|
||||||
|
If you have a non-default SSH configuration on the Barman
|
||||||
|
server, e.g. using a port other than 22, then you can set those
|
||||||
|
parameters in a dedicated Host section in <filename>~/.ssh/config</filename>
|
||||||
|
corresponding to the value of<varname>barman_host</varname> in
|
||||||
|
<filename>repmgr.conf</filename>. See the <literal>Host</literal>
|
||||||
|
section in <command>man 5 ssh_config</command> for more details.
|
||||||
|
</simpara>
|
||||||
|
</tip>
|
||||||
|
<para>
|
||||||
|
It's now possible to clone a standby from Barman, e.g.:
|
||||||
|
<programlisting>
|
||||||
|
NOTICE: using configuration file "/etc/repmgr.conf"
|
||||||
|
NOTICE: destination directory "/var/lib/postgresql/data" provided
|
||||||
|
INFO: connecting to Barman server to verify backup for test_cluster
|
||||||
|
INFO: checking and correcting permissions on existing directory "/var/lib/postgresql/data"
|
||||||
|
INFO: creating directory "/var/lib/postgresql/data/repmgr"...
|
||||||
|
INFO: connecting to Barman server to fetch server parameters
|
||||||
|
INFO: connecting to upstream node
|
||||||
|
INFO: connected to source node, checking its state
|
||||||
|
INFO: successfully connected to source node
|
||||||
|
DETAIL: current installation size is 29 MB
|
||||||
|
NOTICE: retrieving backup from Barman...
|
||||||
|
receiving file list ...
|
||||||
|
(...)
|
||||||
|
NOTICE: standby clone (from Barman) complete
|
||||||
|
NOTICE: you can now start your PostgreSQL server
|
||||||
|
HINT: for example: pg_ctl -D /var/lib/postgresql/data start</programlisting>
|
||||||
|
|
||||||
|
</para>
|
||||||
|
</sect2>
|
||||||
|
<sect2 id="cloning-from-barman-restore-command" xreflabel="Using Barman as a WAL file source">
|
||||||
|
<title>Using Barman as a WAL file source</title>
|
||||||
|
<para>
|
||||||
|
As a fallback in case streaming replication is interrupted, PostgreSQL can optionally
|
||||||
|
retrieve WAL files from an archive, such as that provided by Barman. This is done by
|
||||||
|
setting <varname>restore_command</varname> in <filename>recovery.conf</filename> to
|
||||||
|
a valid shell command which can retrieve a specified WAL file from the archive.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
<command>barman-wal-restore</command> is a Python script provided as part of the <literal>barman-cli</literal>
|
||||||
|
package (Barman 2.0 and later; for Barman 1.x the script is provided separately as
|
||||||
|
<command>barman-wal-restore.py</command>) which performs this function for Barman.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
To use <command>barman-wal-restore</command> with &repmgr;
|
||||||
|
and assuming Barman is located on the <literal>barmansrv</literal> host
|
||||||
|
and that <command>barman-wal-restore</command> is located as an executable at
|
||||||
|
<filename>/usr/bin/barman-wal-restore</filename>,
|
||||||
|
<filename>repmgr.conf</filename> should include the following lines:
|
||||||
|
<programlisting>
|
||||||
|
barman_host=barmansrv
|
||||||
|
barman_server=somedb
|
||||||
|
restore_command=/usr/bin/barman-wal-restore barmansrv somedb %f %p</programlisting>
|
||||||
|
</para>
|
||||||
|
<note>
|
||||||
|
<simpara>
|
||||||
|
<command>barman-wal-restore</command> supports command line switches to
|
||||||
|
control parallelism (<literal>--parallel=N</literal>) and compression (
|
||||||
|
<literal>--bzip2</literal>, <literal>--gzip</literal>).
|
||||||
|
</simpara>
|
||||||
|
</note>
|
||||||
|
<note>
|
||||||
|
<para>
|
||||||
|
To use a non-default Barman configuration file on the Barman server,
|
||||||
|
specify this in <filename>repmgr.conf</filename> with <filename>barman_config</filename>:
|
||||||
|
<programlisting>
|
||||||
|
barman_config=/path/to/barman.conf</programlisting>
|
||||||
|
</para>
|
||||||
|
</note>
|
||||||
|
</sect2>
|
||||||
|
</sect1>
|
||||||
|
|
||||||
|
<sect1 id="cloning-replication-slots" xreflabel="Cloning and replication slots">
|
||||||
|
<indexterm>
|
||||||
|
<primary>cloning</primary>
|
||||||
|
<secondary>replication slots</secondary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<indexterm>
|
||||||
|
<primary>replication slots</primary>
|
||||||
|
<secondary>cloning</secondary>
|
||||||
|
</indexterm>
|
||||||
|
<title>Cloning and replication slots</title>
|
||||||
|
<para>
|
||||||
|
Replication slots were introduced with PostgreSQL 9.4 and are designed to ensure
|
||||||
|
that any standby connected to the primary using a replication slot will always
|
||||||
|
be able to retrieve the required WAL files. This removes the need to manually
|
||||||
|
manage WAL file retention by estimating the number of WAL files that need to
|
||||||
|
be maintained on the primary using <varname>wal_keep_segments</varname>.
|
||||||
|
Do however be aware that if a standby is disconnected, WAL will continue to
|
||||||
|
accumulate on the primary until either the standby reconnects or the replication
|
||||||
|
slot is dropped.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
To enable &repmgr; to use replication slots, set the boolean parameter
|
||||||
|
<varname>use_replication_slots</varname> in <filename>repmgr.conf</filename>:
|
||||||
|
<programlisting>
|
||||||
|
use_replication_slots=true
|
||||||
|
</programlisting>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Replication slots must be enabled in <filename>postgresql.conf</filename>` by
|
||||||
|
setting the parameter <varname>max_replication_slots</varname> to at least the
|
||||||
|
number of expected standbys (changes to this parameter require a server restart).
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
When cloning a standby, &repmgr; will automatically generate an appropriate
|
||||||
|
slot name, which is stored in the <literal>repmgr.nodes</literal> table, and create the slot
|
||||||
|
on the upstream node:
|
||||||
|
<programlisting>
|
||||||
|
repmgr=# SELECT node_id, upstream_node_id, active, node_name, type, priority, slot_name
|
||||||
|
FROM repmgr.nodes ORDER BY node_id;
|
||||||
|
node_id | upstream_node_id | active | node_name | type | priority | slot_name
|
||||||
|
---------+------------------+--------+-----------+---------+----------+---------------
|
||||||
|
1 | | t | node1 | primary | 100 | repmgr_slot_1
|
||||||
|
2 | 1 | t | node2 | standby | 100 | repmgr_slot_2
|
||||||
|
3 | 1 | t | node3 | standby | 100 | repmgr_slot_3
|
||||||
|
(3 rows)</programlisting>
|
||||||
|
|
||||||
|
<programlisting>
|
||||||
|
repmgr=# SELECT slot_name, slot_type, active, active_pid FROM pg_replication_slots ;
|
||||||
|
slot_name | slot_type | active | active_pid
|
||||||
|
---------------+-----------+--------+------------
|
||||||
|
repmgr_slot_2 | physical | t | 23658
|
||||||
|
repmgr_slot_3 | physical | t | 23687
|
||||||
|
(2 rows)</programlisting>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Note that a slot name will be created by default for the primary but not
|
||||||
|
actually used unless the primary is converted to a standby using e.g.
|
||||||
|
<command>repmgr standby switchover</command>.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Further information on replication slots in the PostgreSQL documentation:
|
||||||
|
<ulink url="https://www.postgresql.org/docs/current/interactive/warm-standby.html#STREAMING-REPLICATION-SLOTS">https://www.postgresql.org/docs/current/interactive/warm-standby.html#STREAMING-REPLICATION-SLOTS</ulink>
|
||||||
|
</para>
|
||||||
|
<tip>
|
||||||
|
<simpara>
|
||||||
|
While replication slots can be useful for streaming replication, it's
|
||||||
|
recommended to monitor for inactive slots as these will cause WAL files to
|
||||||
|
build up indefinitely, possibly leading to server failure.
|
||||||
|
</simpara>
|
||||||
|
<simpara>
|
||||||
|
As an alternative we recommend using 2ndQuadrant's <ulink url="https://www.pgbarman.org/">Barman</ulink>,
|
||||||
|
which offloads WAL management to a separate server, negating the need to use replication
|
||||||
|
slots to reserve WAL. See section <xref linkend="cloning-from-barman">
|
||||||
|
for more details on using &repmgr; together with Barman.
|
||||||
|
</simpara>
|
||||||
|
</tip>
|
||||||
|
</sect1>
|
||||||
|
|
||||||
|
<sect1 id="cloning-cascading" xreflabel="Cloning and cascading replication">
|
||||||
|
<indexterm>
|
||||||
|
<primary>cloning</primary>
|
||||||
|
<secondary>cascading replication</secondary>
|
||||||
|
</indexterm>
|
||||||
|
<title>Cloning and cascading replication</title>
|
||||||
|
<para>
|
||||||
|
Cascading replication, introduced with PostgreSQL 9.2, enables a standby server
|
||||||
|
to replicate from another standby server rather than directly from the primary,
|
||||||
|
meaning replication changes "cascade" down through a hierarchy of servers. This
|
||||||
|
can be used to reduce load on the primary and minimize bandwith usage between
|
||||||
|
sites. For more details, see the
|
||||||
|
<ulink url="https://www.postgresql.org/docs/current/static/warm-standby.html#CASCADING-REPLICATION">
|
||||||
|
PostgreSQL cascading replication documentation</ulink>.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
&repmgr; supports cascading replication. When cloning a standby,
|
||||||
|
set the command-line parameter <literal>--upstream-node-id</literal> to the
|
||||||
|
<varname>node_id</varname> of the server the standby should connect to, and
|
||||||
|
&repmgr; will create <filename>recovery.conf</filename> to point to it. Note
|
||||||
|
that if <literal>--upstream-node-id</literal> is not explicitly provided,
|
||||||
|
&repmgr; will set the standby's <filename>recovery.conf</filename> to
|
||||||
|
point to the primary node.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
To demonstrate cascading replication, first ensure you have a primary and standby
|
||||||
|
set up as shown in the <xref linkend="quickstart">.
|
||||||
|
Then create an additional standby server with <filename>repmgr.conf</filename> looking
|
||||||
|
like this:
|
||||||
|
<programlisting>
|
||||||
|
node_id=3
|
||||||
|
node_name=node3
|
||||||
|
conninfo='host=node3 user=repmgr dbname=repmgr'
|
||||||
|
data_directory='/var/lib/postgresql/data'</programlisting>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Clone this standby (using the connection parameters for the existing standby),
|
||||||
|
ensuring <literal>--upstream-node-id</literal> is provide with the <varname>node_id</varname>
|
||||||
|
of the previously created standby (if following the example, this will be <literal>2</literal>):
|
||||||
|
<programlisting>
|
||||||
|
$ repmgr -h node2 -U repmgr -d repmgr -f /etc/repmgr.conf standby clone --upstream-node-id=2
|
||||||
|
NOTICE: using configuration file "/etc/repmgr.conf"
|
||||||
|
NOTICE: destination directory "/var/lib/postgresql/data" provided
|
||||||
|
INFO: connecting to upstream node
|
||||||
|
INFO: connected to source node, checking its state
|
||||||
|
NOTICE: checking for available walsenders on upstream node (2 required)
|
||||||
|
INFO: sufficient walsenders available on upstream node (2 required)
|
||||||
|
INFO: successfully connected to source node
|
||||||
|
DETAIL: current installation size is 29 MB
|
||||||
|
INFO: creating directory "/var/lib/postgresql/data"...
|
||||||
|
NOTICE: starting backup (using pg_basebackup)...
|
||||||
|
HINT: this may take some time; consider using the -c/--fast-checkpoint option
|
||||||
|
INFO: executing: 'pg_basebackup -l "repmgr base backup" -D /var/lib/postgresql/data -h node2 -U repmgr -X stream '
|
||||||
|
NOTICE: standby clone (using pg_basebackup) complete
|
||||||
|
NOTICE: you can now start your PostgreSQL server
|
||||||
|
HINT: for example: pg_ctl -D /var/lib/postgresql/data start</programlisting>
|
||||||
|
|
||||||
|
then register it (note that <literal>--upstream-node-id</literal> must be provided here
|
||||||
|
too):
|
||||||
|
<programlisting>
|
||||||
|
$ repmgr -f /etc/repmgr.conf standby register --upstream-node-id=2
|
||||||
|
NOTICE: standby node "node2" (ID: 2) successfully registered
|
||||||
|
</programlisting>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
After starting the standby, the cluster will look like this, showing that <literal>node3</literal>
|
||||||
|
is attached to <literal>node2</literal>, not the primary (<literal>node1</literal>).
|
||||||
|
<programlisting>
|
||||||
|
$ repmgr -f /etc/repmgr.conf cluster show
|
||||||
|
ID | Name | Role | Status | Upstream | Location | Connection string
|
||||||
|
----+-------+---------+-----------+----------+----------+--------------------------------------
|
||||||
|
1 | node1 | primary | * running | | default | host=node1 dbname=repmgr user=repmgr
|
||||||
|
2 | node2 | standby | running | node1 | default | host=node2 dbname=repmgr user=repmgr
|
||||||
|
3 | node3 | standby | running | node2 | default | host=node3 dbname=repmgr user=repmgr
|
||||||
|
</programlisting>
|
||||||
|
</para>
|
||||||
|
<tip>
|
||||||
|
<simpara>
|
||||||
|
Under some circumstances when setting up a cascading replication
|
||||||
|
cluster, you may wish to clone a downstream standby whose upstream node
|
||||||
|
does not yet exist. In this case you can clone from the primary (or
|
||||||
|
another upstream node); provide the parameter <literal>--upstream-conninfo</literal>
|
||||||
|
to explictly set the upstream's <varname>primary_conninfo</varname> string
|
||||||
|
in <filename>recovery.conf</filename>.
|
||||||
|
</simpara>
|
||||||
|
</tip>
|
||||||
|
</sect1>
|
||||||
|
|
||||||
|
<sect1 id="cloning-advanced" xreflabel="Advanced cloning options">
|
||||||
|
<indexterm>
|
||||||
|
<primary>cloning</primary>
|
||||||
|
<secondary>advanced options</secondary>
|
||||||
|
</indexterm>
|
||||||
|
<title>Advanced cloning options</title>
|
||||||
|
|
||||||
|
<sect2 id="cloning-advanced-pg-basebackup-options" xreflabel="pg_basebackup options when cloning a standby">
|
||||||
|
<title>pg_basebackup options when cloning a standby</title>
|
||||||
|
<para>
|
||||||
|
By default, <command>pg_basebackup</command> performs a checkpoint before beginning the backup
|
||||||
|
process. However, a normal checkpoint may take some time to complete;
|
||||||
|
a fast checkpoint can be forced with the <literal>-c/--fast-checkpoint</literal> option.
|
||||||
|
However this may impact performance of the server being cloned from
|
||||||
|
so should be used with care.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Further options can be passed to the <command>pg_basebackup</command> utility via
|
||||||
|
the setting <varname>pg_basebackup_options</varname> in <filename>repmgr.conf</filename>.
|
||||||
|
See the <ulink url="https://www.postgresql.org/docs/current/static/app-pgbasebackup.html">PostgreSQL pg_basebackup documentation</ulink>
|
||||||
|
for more details of available options.
|
||||||
|
</para>
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
<sect2 id="cloning-advanced-managing-passwords" xreflabel="Managing passwords">
|
||||||
|
<title>Managing passwords</title>
|
||||||
|
<para>
|
||||||
|
If replication connections to a standby's upstream server are password-protected,
|
||||||
|
the standby must be able to provide the password so it can begin streaming
|
||||||
|
replication.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The recommended way to do this is to store the password in the <literal>postgres</literal> system
|
||||||
|
user's <filename>~/.pgpass</filename> file. It's also possible to store the password in the
|
||||||
|
environment variable <varname>PGPASSWORD</varname>, however this is not recommended for
|
||||||
|
security reasons. For more details see the
|
||||||
|
<ulink url="https://www.postgresql.org/docs/current/static/libpq-pgpass.html">PostgreSQL password file documentation</ulink>.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
If, for whatever reason, you wish to include the password in <filename>recovery.conf</filename>,
|
||||||
|
set <varname>use_primary_conninfo_password</varname> to <literal>true</literal> in
|
||||||
|
<filename>repmgr.conf</filename>. This will read a password set in <varname>PGPASSWORD</varname>
|
||||||
|
(but not <filename>~/.pgpass</filename>) and place it into the <literal>primary_conninfo</literal>
|
||||||
|
string in <filename>recovery.conf</filename>. Note that <varname>PGPASSWORD</varname>
|
||||||
|
will need to be set during any action which causes <filename>recovery.conf</filename> to be
|
||||||
|
rewritten, e.g. <xref linkend="repmgr-standby-follow">.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
It is of course also possible to include the password value in the <varname>conninfo</varname>
|
||||||
|
string for each node, but this is obviously a security risk and should be
|
||||||
|
avoided.
|
||||||
|
</para>
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
<sect2 id="cloning-advanced-replication-user" xreflabel="Separate replication user">
|
||||||
|
<title>Separate replication user</title>
|
||||||
|
<para>
|
||||||
|
In some circumstances it might be desirable to create a dedicated replication-only
|
||||||
|
user (in addition to the user who manages the &repmgr; metadata). In this case,
|
||||||
|
the replication user should be set in <filename>repmgr.conf</filename> via the parameter
|
||||||
|
<varname>replication_user</varname>; &repmgr; will use this value when making
|
||||||
|
replication connections and generating <filename>recovery.conf</filename>. This
|
||||||
|
value will also be stored in the <literal>repmgr.nodes</literal>
|
||||||
|
table for each node; it no longer needs to be explicitly specified when
|
||||||
|
cloning a node or executing <xref linkend="repmgr-standby-follow">.
|
||||||
|
</para>
|
||||||
|
</sect2>
|
||||||
|
</sect1>
|
||||||
|
|
||||||
|
|
||||||
|
</chapter>
|
||||||
114
doc/configuration-file-settings.sgml
Normal file
114
doc/configuration-file-settings.sgml
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
<sect1 id="configuration-file-settings" xreflabel="configuration file settings">
|
||||||
|
<title>Configuration file settings</title>
|
||||||
|
<para>
|
||||||
|
Each <filename>repmgr.conf</filename> file must contain the following parameters:
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
<variablelist>
|
||||||
|
<varlistentry id="repmgr-conf-node-id" xreflabel="node_id">
|
||||||
|
<term><varname>node_id</varname> (<type>int</type>)
|
||||||
|
<indexterm>
|
||||||
|
<primary><varname>node_id</varname> configuration file parameter</primary>
|
||||||
|
</indexterm>
|
||||||
|
</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
A unique integer greater than zero which identifies the node.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry id="repmgr-conf-node-name" xreflabel="node_name">
|
||||||
|
<term><varname>node_name</varname> (<type>string</type>)
|
||||||
|
<indexterm>
|
||||||
|
<primary><varname>node_name</varname> configuration file parameter</primary>
|
||||||
|
</indexterm>
|
||||||
|
</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
An arbitrary (but unique) string; we recommend using the server's hostname
|
||||||
|
or another identifier unambiguously associated with the server to avoid
|
||||||
|
confusion. Avoid choosing names which reflect the node's current role,
|
||||||
|
e.g. <varname>primary</varname> or <varname>standby1</varname>
|
||||||
|
as roles can change and if you end up in a solution where the current primary is
|
||||||
|
called <varname>standby1</varname> (for example), things will be confusing
|
||||||
|
to say the least.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry id="repmgr-conf-conninfo" xreflabel="conninfo">
|
||||||
|
<term><varname>conninfo</varname> (<type>string</type>)
|
||||||
|
<indexterm>
|
||||||
|
<primary><varname>conninfo</varname> configuration file parameter</primary>
|
||||||
|
</indexterm>
|
||||||
|
</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Database connection information as a conninfo string.
|
||||||
|
All servers in the cluster must be able to connect to
|
||||||
|
the local node using this string.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
For details on conninfo strings, see section <ulink
|
||||||
|
url="https://www.postgresql.org/docs/current/static/libpq-connect.html#LIBPQ-CONNSTRING">Connection Strings</>
|
||||||
|
in the PosgreSQL documentation.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
If repmgrd is in use, consider explicitly setting
|
||||||
|
<varname>connect_timeout</varname> in the <varname>conninfo</varname>
|
||||||
|
string to determine the length of time which elapses before a network
|
||||||
|
connection attempt is abandoned; for details see <ulink
|
||||||
|
url="https://www.postgresql.org/docs/current/static/libpq-connect.html#LIBPQ-CONNECT-CONNECT-TIMEOUT">
|
||||||
|
the PostgreSQL documentation</>.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry id="repmgr-conf-data-directory" xreflabel="data_directory">
|
||||||
|
<term><varname>data_directory</varname> (<type>string</type>)
|
||||||
|
<indexterm>
|
||||||
|
<primary><varname>data_directory</varname> configuration file parameter</primary>
|
||||||
|
</indexterm>
|
||||||
|
</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
The node's data directory. This is needed by repmgr
|
||||||
|
when performing operations when the PostgreSQL instance
|
||||||
|
is not running and there's no other way of determining
|
||||||
|
the data directory.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
|
||||||
|
</variablelist>
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
For a full list of annotated configuration items, see the file
|
||||||
|
<ulink url="https://raw.githubusercontent.com/2ndQuadrant/repmgr/master/repmgr.conf.sample">repmgr.conf.sample</>.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<note>
|
||||||
|
<para>
|
||||||
|
The following parameters in the configuration file can be overridden with
|
||||||
|
command line options:
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
<literal>-L/--log-level</literal> overrides <literal>log_level</literal> in
|
||||||
|
<filename>repmgr.conf</filename>
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
<literal>-b/--pg_bindir</literal> overrides <literal>pg_bindir</literal> in
|
||||||
|
<filename>repmgr.conf</filename>
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
</para>
|
||||||
|
</note>
|
||||||
|
|
||||||
|
</sect1>
|
||||||
46
doc/configuration-file.sgml
Normal file
46
doc/configuration-file.sgml
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
<sect1 id="configuration-file" xreflabel="configuration file location">
|
||||||
|
<title>Configuration file location</title>
|
||||||
|
<para>
|
||||||
|
<application>repmgr</application> and <application>repmgrd</application>
|
||||||
|
use a common configuration file, by default called
|
||||||
|
<filename>repmgr.conf</filename> (although any name can be used if explicitly specified).
|
||||||
|
<filename>repmgr.conf</filename> must contain a number of required parameters, including
|
||||||
|
the database connection string for the local node and the location
|
||||||
|
of its data directory; other values will be inferred from defaults if
|
||||||
|
not explicitly supplied. See section `configuration file parameters`
|
||||||
|
for more details.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
The configuration file will be searched for in the following locations:
|
||||||
|
<itemizedlist spacing="compact" mark="bullet">
|
||||||
|
<listitem>
|
||||||
|
<para>a configuration file specified by the `-f/--config-file` command line option</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
a location specified by the package maintainer (if <application>repmgr</application>
|
||||||
|
as installed from a package and the package maintainer has specified the configuration
|
||||||
|
file location)
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para><filename>repmgr.conf</filename> in the local directory</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para><filename>/etc/repmgr.conf</filename></para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>the directory reported by <application>pg_config --sysconfdir</application></para>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Note that if a file is explicitly specified with <application>-f/--config-file</application>,
|
||||||
|
an error will be raised if it is not found or not readable and no attempt will be made to
|
||||||
|
check default locations; this is to prevent <application>repmgr</application> unexpectedly
|
||||||
|
reading the wrong file.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
</sect1>
|
||||||
7
doc/configuration.sgml
Normal file
7
doc/configuration.sgml
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<chapter id="configuration" xreflabel="Configuration">
|
||||||
|
<title>repmgr configuration</title>
|
||||||
|
|
||||||
|
&configuration-file;
|
||||||
|
&configuration-file-settings;
|
||||||
|
|
||||||
|
</chapter>
|
||||||
181
doc/event-notifications.sgml
Normal file
181
doc/event-notifications.sgml
Normal file
@@ -0,0 +1,181 @@
|
|||||||
|
<chapter id="event-notifications" xreflabel="event notifications">
|
||||||
|
<title>Event Notifications</title>
|
||||||
|
<para>
|
||||||
|
Each time `repmgr` or `repmgrd` perform a significant event, a record
|
||||||
|
of that event is written into the `repmgr.events` table together with
|
||||||
|
a timestamp, an indication of failure or success, and further details
|
||||||
|
if appropriate. This is useful for gaining an overview of events
|
||||||
|
affecting the replication cluster. However note that this table has
|
||||||
|
advisory character and should be used in combination with the `repmgr`
|
||||||
|
and PostgreSQL logs to obtain details of any events.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Example output after a primary was registered and a standby cloned
|
||||||
|
and registered:
|
||||||
|
<programlisting>
|
||||||
|
repmgr=# SELECT * from repmgr.events ;
|
||||||
|
node_id | event | successful | event_timestamp | details
|
||||||
|
---------+------------------+------------+-------------------------------+-------------------------------------------------------------------------------------
|
||||||
|
1 | primary_register | t | 2016-01-08 15:04:39.781733+09 |
|
||||||
|
2 | standby_clone | t | 2016-01-08 15:04:49.530001+09 | Cloned from host 'repmgr_node1', port 5432; backup method: pg_basebackup; --force: N
|
||||||
|
2 | standby_register | t | 2016-01-08 15:04:50.621292+09 |
|
||||||
|
(3 rows)</programlisting>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Alternatively, use <xref linkend="repmgr-cluster-event"> to output a
|
||||||
|
formatted list of events.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Additionally, event notifications can be passed to a user-defined program
|
||||||
|
or script which can take further action, e.g. send email notifications.
|
||||||
|
This is done by setting the `event_notification_command` parameter in
|
||||||
|
`repmgr.conf`.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
This parameter accepts the following format placeholders:
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<variablelist>
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>%n</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
node ID
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>%e</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
event type
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>%t</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
success (1 or 0)
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>%t</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
timestamp
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>%d</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
details
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
<para>
|
||||||
|
The values provided for <literal>%t</literal> and <literal>%d</literal>
|
||||||
|
will probably contain spaces, so should be quoted in the provided command
|
||||||
|
configuration, e.g.:
|
||||||
|
<programlisting>
|
||||||
|
event_notification_command='/path/to/some/script %n %e %s "%t" "%d"'
|
||||||
|
</programlisting>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Additionally the following format placeholders are available for the event
|
||||||
|
type <varname>bdr_failover</varname> and optionally <varname>bdr_recovery</varname>:
|
||||||
|
</para>
|
||||||
|
<variablelist>
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>%c</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
conninfo string of the next available node
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>%a</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
name of the next available node
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
<para>
|
||||||
|
These should always be quoted.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
By default, all notification types will be passed to the designated script;
|
||||||
|
the notification types can be filtered to explicitly named ones:
|
||||||
|
<itemizedlist spacing="compact" mark="bullet">
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara><literal>primary_register</literal></simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara><literal>standby_register</literal></simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara><literal>standby_unregister</literal></simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara><literal>standby_clone</literal></simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara><literal>standby_promote</literal></simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara><literal>standby_follow</literal></simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara><literal>standby_disconnect_manual</literal></simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara><literal>repmgrd_start</literal></simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara><literal>repmgrd_shutdown</literal></simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara><literal>repmgrd_failover_promote</literal></simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara><literal>repmgrd_failover_follow</literal></simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara><literal>bdr_failover</literal></simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara><literal>bdr_reconnect</literal></simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara><literal>bdr_recovery</literal></simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara><literal>bdr_register</literal></simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara><literal>bdr_unregister</literal></simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
</itemizedlist>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Note that under some circumstances (e.g. when no replication cluster primary
|
||||||
|
could be located), it will not be possible to write an entry into the
|
||||||
|
<literal>repmgr.events</literal>
|
||||||
|
table, in which case executing a script via <varname>event_notification_command</varname>
|
||||||
|
can serve as a fallback by generating some form of notification.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
|
||||||
|
</chapter>
|
||||||
77
doc/filelist.sgml
Normal file
77
doc/filelist.sgml
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
<!-- doc/filelist.sgml -->
|
||||||
|
|
||||||
|
<!ENTITY legal SYSTEM "legal.sgml">
|
||||||
|
|
||||||
|
<!ENTITY bookindex SYSTEM "bookindex.sgml">
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Some parts of the documentation are also source for some plain-text
|
||||||
|
files used during installation. To selectively ignore or include
|
||||||
|
some parts (e.g., external xref's) when generating these files we use
|
||||||
|
these parameter entities. See also standalone-install.sgml.
|
||||||
|
-->
|
||||||
|
<!ENTITY % standalone-ignore "INCLUDE">
|
||||||
|
<!ENTITY % standalone-include "IGNORE">
|
||||||
|
|
||||||
|
<!-- doc/filelist.sgml -->
|
||||||
|
|
||||||
|
<!--
|
||||||
|
By default, no index is included. Use -i include-index on the command line
|
||||||
|
to include it.
|
||||||
|
-->
|
||||||
|
<!ENTITY % include-index "IGNORE">
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Create empty index element for processing by XSLT stylesheet.
|
||||||
|
-->
|
||||||
|
<!ENTITY % include-xslt-index "IGNORE">
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Include external documentation sections
|
||||||
|
-->
|
||||||
|
|
||||||
|
<!ENTITY overview SYSTEM "overview.sgml">
|
||||||
|
<!ENTITY install SYSTEM "install.sgml">
|
||||||
|
<!ENTITY install-requirements SYSTEM "install-requirements.sgml">
|
||||||
|
<!ENTITY install-packages SYSTEM "install-packages.sgml">
|
||||||
|
<!ENTITY install-source SYSTEM "install-source.sgml">
|
||||||
|
<!ENTITY quickstart SYSTEM "quickstart.sgml">
|
||||||
|
<!ENTITY configuration SYSTEM "configuration.sgml">
|
||||||
|
<!ENTITY configuration-file SYSTEM "configuration-file.sgml">
|
||||||
|
<!ENTITY configuration-file-settings SYSTEM "configuration-file-settings.sgml">
|
||||||
|
<!ENTITY cloning-standbys SYSTEM "cloning-standbys.sgml">
|
||||||
|
<!ENTITY promoting-standby SYSTEM "promoting-standby.sgml">
|
||||||
|
<!ENTITY follow-new-primary SYSTEM "follow-new-primary.sgml">
|
||||||
|
<!ENTITY switchover SYSTEM "switchover.sgml">
|
||||||
|
<!ENTITY event-notifications SYSTEM "event-notifications.sgml">
|
||||||
|
<!ENTITY upgrading-repmgr SYSTEM "upgrading-repmgr.sgml">
|
||||||
|
|
||||||
|
<!ENTITY repmgrd-automatic-failover SYSTEM "repmgrd-automatic-failover.sgml">
|
||||||
|
<!ENTITY repmgrd-configuration SYSTEM "repmgrd-configuration.sgml">
|
||||||
|
<!ENTITY repmgrd-demonstration SYSTEM "repmgrd-demonstration.sgml">
|
||||||
|
<!ENTITY repmgrd-monitoring SYSTEM "repmgrd-monitoring.sgml">
|
||||||
|
<!ENTITY repmgrd-degraded-monitoring SYSTEM "repmgrd-degraded-monitoring.sgml">
|
||||||
|
<!ENTITY repmgrd-cascading-replication SYSTEM "repmgrd-cascading-replication.sgml">
|
||||||
|
<!ENTITY repmgrd-network-split SYSTEM "repmgrd-network-split.sgml">
|
||||||
|
|
||||||
|
<!ENTITY repmgr-primary-register SYSTEM "repmgr-primary-register.sgml">
|
||||||
|
<!ENTITY repmgr-primary-unregister SYSTEM "repmgr-primary-unregister.sgml">
|
||||||
|
<!ENTITY repmgr-standby-clone SYSTEM "repmgr-standby-clone.sgml">
|
||||||
|
<!ENTITY repmgr-standby-register SYSTEM "repmgr-standby-register.sgml">
|
||||||
|
<!ENTITY repmgr-standby-unregister SYSTEM "repmgr-standby-unregister.sgml">
|
||||||
|
<!ENTITY repmgr-standby-promote SYSTEM "repmgr-standby-promote.sgml">
|
||||||
|
<!ENTITY repmgr-standby-follow SYSTEM "repmgr-standby-follow.sgml">
|
||||||
|
<!ENTITY repmgr-standby-switchover SYSTEM "repmgr-standby-switchover.sgml">
|
||||||
|
<!ENTITY repmgr-node-status SYSTEM "repmgr-node-status.sgml">
|
||||||
|
<!ENTITY repmgr-node-check SYSTEM "repmgr-node-check.sgml">
|
||||||
|
<!ENTITY repmgr-node-rejoin SYSTEM "repmgr-node-rejoin.sgml">
|
||||||
|
<!ENTITY repmgr-cluster-show SYSTEM "repmgr-cluster-show.sgml">
|
||||||
|
<!ENTITY repmgr-cluster-matrix SYSTEM "repmgr-cluster-matrix.sgml">
|
||||||
|
<!ENTITY repmgr-cluster-crosscheck SYSTEM "repmgr-cluster-crosscheck.sgml">
|
||||||
|
<!ENTITY repmgr-cluster-event SYSTEM "repmgr-cluster-event.sgml">
|
||||||
|
<!ENTITY repmgr-cluster-cleanup SYSTEM "repmgr-cluster-cleanup.sgml">
|
||||||
|
|
||||||
|
<!ENTITY appendix-signatures SYSTEM "appendix-signatures.sgml">
|
||||||
|
|
||||||
|
<!ENTITY bookindex SYSTEM "bookindex.sgml">
|
||||||
|
|
||||||
42
doc/follow-new-primary.sgml
Normal file
42
doc/follow-new-primary.sgml
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
<chapter id="follow-new-primary" xreflabel="Following a new primary">
|
||||||
|
<title>Following a new primary</title>
|
||||||
|
<para>
|
||||||
|
Following the failure or removal of the replication cluster's existing primary
|
||||||
|
server, <xref linkend="repmgr-standby-follow"> can be used to make 'orphaned' standbys
|
||||||
|
follow the new primary and catch up to its current state.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
To demonstrate this, assuming a replication cluster in the same state as the
|
||||||
|
end of the preceding section (<xref linkend="promoting-standby">),
|
||||||
|
execute this:
|
||||||
|
<programlisting>
|
||||||
|
$ repmgr -f /etc/repmgr.conf repmgr standby follow
|
||||||
|
INFO: changing node 3's primary to node 2
|
||||||
|
NOTICE: restarting server using "pg_ctl -l /var/log/postgresql/startup.log -w -D '/var/lib/postgresql/data' restart"
|
||||||
|
waiting for server to shut down......... done
|
||||||
|
server stopped
|
||||||
|
waiting for server to start.... done
|
||||||
|
server started
|
||||||
|
NOTICE: STANDBY FOLLOW successful
|
||||||
|
DETAIL: node 3 is now attached to node 2
|
||||||
|
</programlisting>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The standby is now replicating from the new primary and `repmgr cluster show`
|
||||||
|
output reflects this:
|
||||||
|
<programlisting>
|
||||||
|
$ repmgr -f /etc/repmgr.conf cluster show
|
||||||
|
ID | Name | Role | Status | Upstream | Location | Connection string
|
||||||
|
----+-------+---------+-----------+----------+----------+--------------------------------------
|
||||||
|
1 | node1 | primary | - failed | | default | host=node1 dbname=repmgr user=repmgr
|
||||||
|
2 | node2 | primary | * running | | default | host=node2 dbname=repmgr user=repmgr
|
||||||
|
3 | node3 | standby | running | node2 | default | host=node3 dbname=repmgr user=repmgr</programlisting>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Note that with cascading replication, <command>repmgr standby follow</command> can also be
|
||||||
|
used to detach a standby from its current upstream server and follow the
|
||||||
|
primary. However it's currently not possible to have it follow another standby;
|
||||||
|
we hope to improve this in a future release.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
</chapter>
|
||||||
32
doc/install-packages.sgml
Normal file
32
doc/install-packages.sgml
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
<sect1 id="installation-packages" xreflabel="Installing from packages">
|
||||||
|
<title>Installing &repmgr; from packages</title>
|
||||||
|
<para>
|
||||||
|
We recommend installing `repmgr` using the available packages for your
|
||||||
|
system.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<sect2 id="installation-packages-redhat" xreflabel="Installing from packages on RHEL, Fedora and CentOS">
|
||||||
|
<title>RedHat/Fedora/CentOS</title>
|
||||||
|
<para>
|
||||||
|
RPM packages for `repmgr` are available via Yum through
|
||||||
|
the PostgreSQL Global Development Group RPM repository
|
||||||
|
( <ulink url="https://yum.postgresql.org/">http://yum.postgresql.org/</>).
|
||||||
|
Follow the instructions for your distribution (RedHat, CentOS,
|
||||||
|
Fedora, etc.) and architecture as detailed at yum.postgresql.org.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
2ndQuadrant also provides its own RPM packages which are made available
|
||||||
|
at the same time as each `repmgr` release, as it can take some days for
|
||||||
|
them to become available via the main PGDG repository. See here for details:
|
||||||
|
<ulink url="http://repmgr.org/yum-repository.html">http://repmgr.org/yum-repository.html</>
|
||||||
|
</para>
|
||||||
|
</sect2>
|
||||||
|
<sect2 id="installation-packages-debian" xreflabel="Installing from packages on Debian or Ubuntu">
|
||||||
|
<title>Debian/Ubuntu</title>
|
||||||
|
<para>.deb packages for `repmgr` are available from the
|
||||||
|
PostgreSQL Community APT repository (<ulink url="http://apt.postgresql.org/">http://apt.postgresql.org/</> ).
|
||||||
|
Instructions can be found in the APT section of the PostgreSQL Wiki
|
||||||
|
(<ulink url="https://wiki.postgresql.org/wiki/Apt">https://wiki.postgresql.org/wiki/Apt</> ).
|
||||||
|
</para>
|
||||||
|
</sect2>
|
||||||
|
</sect1>
|
||||||
67
doc/install-requirements.sgml
Normal file
67
doc/install-requirements.sgml
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
<sect1 id="install-requirements" xreflabel="installation requirements">
|
||||||
|
<title>Requirements for installing repmgr</title>
|
||||||
|
<para>
|
||||||
|
repmgr is developed and tested on Linux and OS X, but should work on any
|
||||||
|
UNIX-like system supported by PostgreSQL itself. There is no support for
|
||||||
|
Microsoft Windows.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
From version 4.0, repmgr is compatible with all PostgreSQL versions from 9.4, including PostgreSQL 10.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
PostgreSQL 9.3 is supported by repmgr 3.3.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<note>
|
||||||
|
<simpara>
|
||||||
|
If upgrading from `repmgr 3`, please see the separate upgrade guide
|
||||||
|
`doc/upgrading-from-repmgr3.md`.
|
||||||
|
</simpara>
|
||||||
|
</note>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
All servers in the replication cluster must be running the same major version of
|
||||||
|
PostgreSQL, and we recommend that they also run the same minor version.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
`repmgr` must be installed on each server in the replication cluster.
|
||||||
|
If installing repmgr from packages, the package version must match the PostgreSQL
|
||||||
|
version. If installing from source, repmgr must be compiled against the same
|
||||||
|
major version.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
A dedicated system user for `repmgr` is *not* required; as many `repmgr` and
|
||||||
|
`repmgrd` actions require direct access to the PostgreSQL data directory,
|
||||||
|
these commands should be executed by the `postgres` user.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Passwordless `ssh` connectivity between all servers in the replication cluster
|
||||||
|
is not required, but is necessary in the following cases:
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem>
|
||||||
|
<simpara>if you need `repmgr` to copy configuration files from outside the PostgreSQL
|
||||||
|
data directory (in which case `rsync` is also required)</simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara>to perform switchover operations</simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara>when executing `repmgr cluster matrix` and `repmgr cluster crosscheck`</simpara>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<tip>
|
||||||
|
<simpara>
|
||||||
|
We recommend using a session multiplexer utility such as `screen` or
|
||||||
|
`tmux` when performing long-running actions (such as cloning a database)
|
||||||
|
on a remote server - this will ensure the `repmgr` action won't be prematurely
|
||||||
|
terminated if your `ssh` session to the server is interrupted or closed.
|
||||||
|
</simpara>
|
||||||
|
</tip>
|
||||||
|
</sect1>
|
||||||
139
doc/install-source.sgml
Normal file
139
doc/install-source.sgml
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
<sect1 id="installation-source" xreflabel="Installing from source code">
|
||||||
|
<title>Installing &repmgr; from source</title>
|
||||||
|
|
||||||
|
<sect2 id="installation-source-prereqs">
|
||||||
|
<title>Prerequisites for installing from source</title>
|
||||||
|
<para>
|
||||||
|
To install &repmgr; the prerequisites for compiling
|
||||||
|
&postgres; must be installed. These are described in &postgres;'s
|
||||||
|
documentation
|
||||||
|
on <ulink url="https://www.postgresql.org/docs/current/install-requirements.html">build requirements</ulink>
|
||||||
|
and <ulink url="https://www.postgresql.org/docs/current/docguide-toolsets.html">build requirements for documentation</ulink>.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Most mainstream Linux distributions and other UNIX variants provide simple
|
||||||
|
ways to install the prerequisites from packages.
|
||||||
|
<itemizedlist spacing="compact" mark="bullet">
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<literal>Debian</literal> and <literal>Ubuntu</literal>: First
|
||||||
|
add the <ulink
|
||||||
|
url="http://apt.postgresql.org/">apt.postgresql.org</ulink>
|
||||||
|
repository to your <filename>sources.list</filename> if you
|
||||||
|
have not already done so. Then install the pre-requisites for
|
||||||
|
building PostgreSQL with:
|
||||||
|
<programlisting>
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get build-dep postgresql-9.6
|
||||||
|
</programlisting>
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<literal>RHEL or CentOS 6.x or 7.x</literal>: install the appropriate repository RPM
|
||||||
|
for your system from <ulink url="https://yum.postgresql.org/repopackages.php">
|
||||||
|
yum.postgresql.org</ulink>. Then install the prerequisites for building
|
||||||
|
PostgreSQL with:
|
||||||
|
<programlisting>
|
||||||
|
sudo yum check-update
|
||||||
|
sudo yum groupinstall "Development Tools"
|
||||||
|
sudo yum install yum-utils openjade docbook-dtds docbook-style-dsssl docbook-style-xsl
|
||||||
|
sudo yum-builddep postgresql96
|
||||||
|
</programlisting>
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<note>
|
||||||
|
<simpara>
|
||||||
|
Select the appropriate PostgreSQL versions for your target repmgr version.
|
||||||
|
</simpara>
|
||||||
|
</note>
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
|
||||||
|
<sect2 id="installation-get-source">
|
||||||
|
<title>Getting &repmgr; source code</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
There are two ways to get the &repmgr; source code: with git, or by downloading tarballs of released versions.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<sect3>
|
||||||
|
<title>Using <application>git</application> to get the &repmgr; sources</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Use <application><ulink url="https://git-scm.com">git</ulink></application> if you expect
|
||||||
|
to update often, you want to keep track of development or if you want to contribute
|
||||||
|
changes to &repmgr;. There is no reason <emphasis>not</emphasis> to use <application>git</application>
|
||||||
|
if you're familiar with it.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
The source for &repmgr; is maintained at
|
||||||
|
<ulink url="https://github.com/2ndQuadrant/repmgr">https://github.com/2ndQuadrant/repmgr</ulink>.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
There are also tags for each &repmgr; release, e.g. <filename>REL4_0_STABLE</filename>.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Clone the source code using <application>git</application>:
|
||||||
|
<programlisting>
|
||||||
|
git clone https://github.com/2ndQuadrant/repmgr
|
||||||
|
</programlisting>
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
For more information on using <application>git</application> see
|
||||||
|
<ulink url="https://git-scm.com/">git-scm.com</ulink>.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
</sect3>
|
||||||
|
|
||||||
|
<sect3>
|
||||||
|
<title>Downloading release source tarballs</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Official release source code is uploaded as tarballs to the
|
||||||
|
&repmgr; website along with a tarball checksum and a matching GnuPG
|
||||||
|
signature. See
|
||||||
|
<ulink url="http://repmgr.org/">http://repmgr.org/</ulink>
|
||||||
|
for the download information. See <xref linkend="appendix-signatures">
|
||||||
|
for information on verifying digital signatures.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
You will need to download the repmgr source, e.g. <filename>repmgr-4.0.tar.gz</filename>.
|
||||||
|
You may optionally verify the package checksums from the
|
||||||
|
<literal>.md5</literal> files and/or verify the GnuPG signatures
|
||||||
|
per <xref linkend="appendix-signatures">.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
After you unpack the source code archives using <literal>tar xf</literal>
|
||||||
|
the installation process is the same as if you were installing from a git
|
||||||
|
clone.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
</sect3>
|
||||||
|
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
<sect2 id="installation-repmgr-source">
|
||||||
|
<title>Installation of &repmgr; from source</title>
|
||||||
|
<para>
|
||||||
|
To installing &repmgr; from source, simply execute:
|
||||||
|
|
||||||
|
<programlisting>
|
||||||
|
./configure && make install
|
||||||
|
</programlisting>
|
||||||
|
|
||||||
|
Ensure `pg_config` for the target PostgreSQL version is in `$PATH`.
|
||||||
|
</para>
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
</sect1>
|
||||||
24
doc/install.sgml
Normal file
24
doc/install.sgml
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
<chapter id="installation" xreflabel="Installation">
|
||||||
|
<title>Installation</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
&repmgr; can be installed from binary packages provided by your operating
|
||||||
|
system's packaging system, or from source.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
In general we recommend using binary packages, unless unavailable for your operating system.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Source installs are mainly useful if you want to keep track of the very
|
||||||
|
latest repmgr development and contribute to development. They're also the
|
||||||
|
only option if there are no packages for your operating system yet.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Before installing &repmgr; make sure you satisfy the <xref linkend="install-requirements">.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
&install-requirements;
|
||||||
|
&install-packages;
|
||||||
|
&install-source;
|
||||||
|
|
||||||
|
</chapter>
|
||||||
20
doc/legal.sgml
Normal file
20
doc/legal.sgml
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<!-- doc/src/sgml/legal.sgml -->
|
||||||
|
|
||||||
|
<date>2017</date>
|
||||||
|
|
||||||
|
<copyright>
|
||||||
|
<year>2010-2017</year>
|
||||||
|
<holder>2ndQuadrant, Ltd.</holder>
|
||||||
|
</copyright>
|
||||||
|
|
||||||
|
<legalnotice id="legalnotice">
|
||||||
|
<title>Legal Notice</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
<productname>repmgr</productname> is Copyright © 2010-2017
|
||||||
|
by 2ndQuadrant, Ltd.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>add license</para>
|
||||||
|
|
||||||
|
</legalnotice>
|
||||||
209
doc/overview.sgml
Normal file
209
doc/overview.sgml
Normal file
@@ -0,0 +1,209 @@
|
|||||||
|
<chapter id="overview" xreflabel="Overview">
|
||||||
|
<title>repmgr overview</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
This chapter provides a high-level overview of repmgr's components and functionality.
|
||||||
|
</para>
|
||||||
|
<sect1 id="repmgr-concepts" xreflabel="Concepts">
|
||||||
|
<title>Concepts</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
This guide assumes that you are familiar with PostgreSQL administration and
|
||||||
|
streaming replication concepts. For further details on streaming
|
||||||
|
replication, see the PostgreSQL documentation section on <ulink
|
||||||
|
url="https://www.postgresql.org/docs/current/interactive/warm-standby.html#STREAMING-REPLICATION">
|
||||||
|
streaming replication</>.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The following terms are used throughout the `repmgr` documentation.
|
||||||
|
<variablelist>
|
||||||
|
<varlistentry>
|
||||||
|
<term>replication cluster</term>
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
In the `repmgr` documentation, "replication cluster" refers to the network
|
||||||
|
of PostgreSQL servers connected by streaming replication.
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term>node</term>
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
A node is a server within a replication cluster.
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term>upstream node</term>
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
The node a standby server connects to, in order to receive streaming replication.
|
||||||
|
This is either the primary server or in the case of cascading replication, another
|
||||||
|
standby.
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term>failover</term>
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
This is the action which occurs if a primary server fails and a suitable standby
|
||||||
|
is promoted as the new primary. The `repmgrd` daemon supports automatic failover
|
||||||
|
to minimise downtime.
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term>switchover</term>
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
In certain circumstances, such as hardware or operating system maintenance,
|
||||||
|
it's necessary to take a primary server offline; in this case a controlled
|
||||||
|
switchover is necessary, whereby a suitable standby is promoted and the
|
||||||
|
existing primary removed from the replication cluster in a controlled manner.
|
||||||
|
The `repmgr` command line client provides this functionality.
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term>fencing</term>
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
In a failover situation, following the promotion of a new standby, it's
|
||||||
|
essential that the previous primary does not unexpectedly come back on
|
||||||
|
line, which would result in a split-brain situation. To prevent this,
|
||||||
|
the failed primary should be isolated from applications, i.e. "fenced off".
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
</para>
|
||||||
|
</sect1>
|
||||||
|
<sect1 id="repmgr-components" xreflabel="Components">
|
||||||
|
<title>Components</title>
|
||||||
|
<para>
|
||||||
|
`repmgr` is a suite of open-source tools to manage replication and failover
|
||||||
|
within a cluster of PostgreSQL servers. It supports and enhances PostgreSQL's
|
||||||
|
built-in streaming replication, which provides a single read/write primary server
|
||||||
|
and one or more read-only standbys containing near-real time copies of the primary
|
||||||
|
server's database. It provides two main tools:
|
||||||
|
<variablelist>
|
||||||
|
<varlistentry>
|
||||||
|
<term>repmgr</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
A command-line tool used to perform administrative tasks such as:
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem>
|
||||||
|
<simpara>setting up standby servers</simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara>promoting a standby server to primary</simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara>switching over primary and standby servers</simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara>displaying the status of servers in the replication cluster</simpara>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term>repmgrd</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
A daemon which actively monitors servers in a replication cluster
|
||||||
|
and performs the following tasks:
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem>
|
||||||
|
<simpara>monitoring and recording replication performance</simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara>performing failover by detecting failure of the primary and
|
||||||
|
promoting the most suitable standby server
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara>provide notifications about events in the cluster to a user-defined
|
||||||
|
script which can perform tasks such as sending alerts by email</simpara>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
</para>
|
||||||
|
</sect1>
|
||||||
|
|
||||||
|
<sect1 id="repmgr-user-metadata" xreflabel="Repmgr user and metadata">
|
||||||
|
<title>Repmgr user and metadata</title>
|
||||||
|
<para>
|
||||||
|
In order to effectively manage a replication cluster, `repmgr` needs to store
|
||||||
|
information about the servers in the cluster in a dedicated database schema.
|
||||||
|
This schema is automatically by the `repmgr` extension, which is installed
|
||||||
|
during the first step in initialising a `repmgr`-administered cluster
|
||||||
|
(`repmgr primary register`) and contains the following objects:
|
||||||
|
<variablelist>
|
||||||
|
<varlistentry>
|
||||||
|
<term>Tables</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem>
|
||||||
|
<simpara>repmgr.events: records events of interest</simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara>repmgr.nodes: connection and status information for each server in the
|
||||||
|
replication cluster</simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara>repmgr.monitoring_history: historical standby monitoring information written by `repmgrd`</simpara>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>Views</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem>
|
||||||
|
<simpara>repmgr.show_nodes: based on the table `repl_nodes`, additionally showing the
|
||||||
|
name of the server's upstream node</simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara>repmgr.replication_status: when `repmgrd`'s monitoring is enabled, shows current monitoring
|
||||||
|
status for each standby.</simpara>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
The `repmgr` metadata schema can be stored in an existing database or in its own
|
||||||
|
dedicated database. Note that the `repmgr` metadata schema cannot reside on a database
|
||||||
|
server which is not part of the replication cluster managed by `repmgr`.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
A database user must be available for `repmgr` to access this database and perform
|
||||||
|
necessary changes. This user does not need to be a superuser, however some operations
|
||||||
|
such as initial installation of the `repmgr` extension will require a superuser
|
||||||
|
connection (this can be specified where required with the command line option
|
||||||
|
`--superuser`).
|
||||||
|
</para>
|
||||||
|
</sect1>
|
||||||
|
|
||||||
|
</chapter>
|
||||||
75
doc/promoting-standby.sgml
Normal file
75
doc/promoting-standby.sgml
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
<chapter id="promoting-standby" xreflabel="Promoting a standby">
|
||||||
|
<title>Promoting a standby server with repmgr</title>
|
||||||
|
<para>
|
||||||
|
If a primary server fails or needs to be removed from the replication cluster,
|
||||||
|
a new primary server must be designated, to ensure the cluster continues
|
||||||
|
to function correctly. This can be done with <xref linkend="repmgr-standby-promote">,
|
||||||
|
which promotes the standby on the current server to primary.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
To demonstrate this, set up a replication cluster with a primary and two attached
|
||||||
|
standby servers so that the cluster looks like this:
|
||||||
|
<programlisting>
|
||||||
|
$ repmgr -f /etc/repmgr.conf cluster show
|
||||||
|
ID | Name | Role | Status | Upstream | Location | Connection string
|
||||||
|
----+-------+---------+-----------+----------+----------+--------------------------------------
|
||||||
|
1 | node1 | primary | * running | | default | host=node1 dbname=repmgr user=repmgr
|
||||||
|
2 | node2 | standby | running | node1 | default | host=node2 dbname=repmgr user=repmgr
|
||||||
|
3 | node3 | standby | running | node1 | default | host=node3 dbname=repmgr user=repmgr</programlisting>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Stop the current primary with e.g.:
|
||||||
|
<programlisting>
|
||||||
|
$ pg_ctl -D /var/lib/postgresql/data -m fast stop</programlisting>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
At this point the replication cluster will be in a partially disabled state, with
|
||||||
|
both standbys accepting read-only connections while attempting to connect to the
|
||||||
|
stopped primary. Note that the &repmgr; metadata table will not yet have been updated;
|
||||||
|
executing <xref linkend="repmgr-cluster-show"> will note the discrepancy:
|
||||||
|
<programlisting>
|
||||||
|
$ repmgr -f /etc/repmgr.conf cluster show
|
||||||
|
ID | Name | Role | Status | Upstream | Location | Connection string
|
||||||
|
----+-------+---------+---------------+----------+----------+--------------------------------------
|
||||||
|
1 | node1 | primary | ? unreachable | | default | host=node1 dbname=repmgr user=repmgr
|
||||||
|
2 | node2 | standby | running | node1 | default | host=node2 dbname=repmgr user=repmgr
|
||||||
|
3 | node3 | standby | running | node1 | default | host=node3 dbname=repmgr user=repmgr
|
||||||
|
|
||||||
|
WARNING: following issues were detected
|
||||||
|
node "node1" (ID: 1) is registered as an active primary but is unreachable</programlisting>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Now promote the first standby with:
|
||||||
|
<programlisting>
|
||||||
|
$ repmgr -f /etc/repmgr.conf standby promote</programlisting>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
This will produce output similar to the following:
|
||||||
|
<programlisting>
|
||||||
|
INFO: connecting to standby database
|
||||||
|
NOTICE: promoting standby
|
||||||
|
DETAIL: promoting server using "pg_ctl -l /var/log/postgresql/startup.log -w -D '/var/lib/postgresql/data' promote"
|
||||||
|
server promoting
|
||||||
|
INFO: reconnecting to promoted server
|
||||||
|
NOTICE: STANDBY PROMOTE successful
|
||||||
|
DETAIL: node 2 was successfully promoted to primary</programlisting>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Executing <xref linkend="repmgr-cluster-show"> will show the current state; as there is now an
|
||||||
|
active primary, the previous warning will not be displayed:
|
||||||
|
<programlisting>
|
||||||
|
$ repmgr -f /etc/repmgr.conf cluster show
|
||||||
|
ID | Name | Role | Status | Upstream | Location | Connection string
|
||||||
|
----+-------+---------+-----------+----------+----------+--------------------------------------
|
||||||
|
1 | node1 | primary | - failed | | default | host=node1 dbname=repmgr user=repmgr
|
||||||
|
2 | node2 | primary | * running | | default | host=node2 dbname=repmgr user=repmgr
|
||||||
|
3 | node3 | standby | running | node1 | default | host=node3 dbname=repmgr user=repmgr</programlisting>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
However the sole remaining standby (<literal>node3</literal>) is still trying to replicate from the failed
|
||||||
|
primary; <xref linkend="repmgr-standby-follow"> must now be executed to rectify this situation
|
||||||
|
(see <xref linkend="follow-new-primary"> for example).
|
||||||
|
</para>
|
||||||
|
</chapter>
|
||||||
|
|
||||||
446
doc/quickstart.sgml
Normal file
446
doc/quickstart.sgml
Normal file
@@ -0,0 +1,446 @@
|
|||||||
|
<chapter id="quickstart" xreflabel="Quick-start guide">
|
||||||
|
<title>Quick-start guide</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
This section gives a quick introduction to &repmgr;, including setting up a
|
||||||
|
sample &repmgr; installation and a basic replication cluster.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
These instructions are not suitable for a production install, as they may not
|
||||||
|
take into account security considerations, proper system administration
|
||||||
|
procedures etc..
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<sect1 id="quickstart-prerequisites">
|
||||||
|
<title>Prerequisites for setting up a basic replication cluster with &repmgr;</title>
|
||||||
|
<para>
|
||||||
|
The following section will describe how to set up a basic replication cluster
|
||||||
|
with a primary and a standby server using the <application>repmgr</application>
|
||||||
|
command line tool.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
We'll assume the primary is called <literal>node1</literal> with IP address
|
||||||
|
<literal>192.168.1.11</literal>, and the standby is called <literal>node2</literal>
|
||||||
|
with IP address <literal>192.168.1.12</literal>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Following software must be installed on both servers:
|
||||||
|
<itemizedlist spacing="compact" mark="bullet">
|
||||||
|
<listitem>
|
||||||
|
<simpara><application>PostgreSQL</application></simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
<application>repmgr</application> (matching the installed
|
||||||
|
<application>PostgreSQL</application> major version)
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
At network level, connections between the PostgreSQL port (default: <literal>5432</literal>)
|
||||||
|
must be possible in both directions.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
If you want <application>repmgr</application> to copy configuration files which are
|
||||||
|
located outside the PostgreSQL data directory, and/or to test <command>switchover</command>
|
||||||
|
functionality, you will also need passwordless SSH connections between both servers, and
|
||||||
|
<application>rsync</application> should be installed.
|
||||||
|
</para>
|
||||||
|
<tip>
|
||||||
|
<simpara>
|
||||||
|
For testing <application>repmgr</application>, it's possible to use multiple PostgreSQL
|
||||||
|
instances running on different ports on the same computer, with
|
||||||
|
passwordless SSH access to <filename>localhost</filename> enabled.
|
||||||
|
</simpara>
|
||||||
|
</tip>
|
||||||
|
</sect1>
|
||||||
|
|
||||||
|
<sect1 id="quickstart-postgresql-configuration">
|
||||||
|
<title>PostgreSQL configuration</title>
|
||||||
|
<para>
|
||||||
|
On the primary server, a PostgreSQL instance must be initialised and running.
|
||||||
|
The following replication settings may need to be adjusted:
|
||||||
|
</para>
|
||||||
|
<programlisting>
|
||||||
|
|
||||||
|
# Enable replication connections; set this figure to at least one more
|
||||||
|
# than the number of standbys which will connect to this server
|
||||||
|
# (note that repmgr will execute `pg_basebackup` in WAL streaming mode,
|
||||||
|
# which requires two free WAL senders)
|
||||||
|
|
||||||
|
max_wal_senders = 10
|
||||||
|
|
||||||
|
# Ensure WAL files contain enough information to enable read-only queries
|
||||||
|
# on the standby.
|
||||||
|
#
|
||||||
|
# PostgreSQL 9.5 and earlier: one of 'hot_standby' or 'logical'
|
||||||
|
# PostgreSQL 9.6 and later: one of 'replica' or 'logical'
|
||||||
|
# ('hot_standby' will still be accepted as an alias for 'replica')
|
||||||
|
#
|
||||||
|
# See: https://www.postgresql.org/docs/current/static/runtime-config-wal.html#GUC-WAL-LEVEL
|
||||||
|
|
||||||
|
wal_level = 'hot_standby'
|
||||||
|
|
||||||
|
# Enable read-only queries on a standby
|
||||||
|
# (Note: this will be ignored on a primary but we recommend including
|
||||||
|
# it anyway)
|
||||||
|
|
||||||
|
hot_standby = on
|
||||||
|
|
||||||
|
# Enable WAL file archiving
|
||||||
|
archive_mode = on
|
||||||
|
|
||||||
|
# Set archive command to a script or application that will safely store
|
||||||
|
# you WALs in a secure place. /bin/true is an example of a command that
|
||||||
|
# ignores archiving. Use something more sensible.
|
||||||
|
archive_command = '/bin/true'
|
||||||
|
|
||||||
|
# If you have configured `pg_basebackup_options`
|
||||||
|
# in `repmgr.conf` to include the setting `--xlog-method=fetch` (from
|
||||||
|
# PostgreSQL 10 `--wal-method=fetch`), *and* you have not set
|
||||||
|
# `restore_command` in `repmgr.conf`to fetch WAL files from another
|
||||||
|
# source such as Barman, you'll need to set `wal_keep_segments` to a
|
||||||
|
# high enough value to ensure that all WAL files generated while
|
||||||
|
# the standby is being cloned are retained until the standby starts up.
|
||||||
|
#
|
||||||
|
# wal_keep_segments = 5000
|
||||||
|
</programlisting>
|
||||||
|
<tip>
|
||||||
|
<simpara>
|
||||||
|
Rather than editing these settings in the default <filename>postgresql.conf</filename>
|
||||||
|
file, create a separate file such as <filename>postgresql.replication.conf</filename> and
|
||||||
|
include it from the end of the main configuration file with:
|
||||||
|
<command>include 'postgresql.replication.conf</command>.
|
||||||
|
</simpara>
|
||||||
|
</tip>
|
||||||
|
</sect1>
|
||||||
|
|
||||||
|
<sect1 id="quickstart-repmgr-user-database">
|
||||||
|
<title>Create the repmgr user and database</title>
|
||||||
|
<para>
|
||||||
|
Create a dedicated PostgreSQL superuser account and a database for
|
||||||
|
the &repmgr; metadata, e.g.
|
||||||
|
</para>
|
||||||
|
<programlisting>
|
||||||
|
createuser -s repmgr
|
||||||
|
createdb repmgr -O repmgr
|
||||||
|
</programlisting>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
For the examples in this document, the name <literal>repmgr</literal> will be
|
||||||
|
used for both user and database, but any names can be used.
|
||||||
|
</para>
|
||||||
|
<note>
|
||||||
|
<para>
|
||||||
|
For the sake of simplicity, the <literal>repmgr</literal> user is created
|
||||||
|
as a superuser. If desired, it's possible to create the <literal>repmgr</literal>
|
||||||
|
user as a normal user. However for certain operations superuser permissions
|
||||||
|
are requiredl; in this case the command line option <command>--superuser</command>
|
||||||
|
can be provided to specify a superuser.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
It's also assumed that the <literal>repmgr</literal> user will be used to make the
|
||||||
|
replication connection from the standby to the primary; again this can be
|
||||||
|
overridden by specifying a separate replication user when registering each node.
|
||||||
|
</para>
|
||||||
|
</note>
|
||||||
|
|
||||||
|
<tip>
|
||||||
|
<para>
|
||||||
|
&repmgr; will install the <literal>repmgr</literal> extension, which creates a
|
||||||
|
<literal>repmgr</literal> schema containing the &repmgr;'s metadata tables as
|
||||||
|
well as other functions and views. We also recommend that you set the
|
||||||
|
<literal>repmgr</literal> user's search path to include this schema name, e.g.
|
||||||
|
<programlisting>
|
||||||
|
ALTER USER repmgr SET search_path TO repmgr, "$user", public;</programlisting>
|
||||||
|
</para>
|
||||||
|
</tip>
|
||||||
|
|
||||||
|
</sect1>
|
||||||
|
|
||||||
|
<sect1 id="quickstart-authentication">
|
||||||
|
<title>Configuring authentication in pg_hba.conf</title>
|
||||||
|
<para>
|
||||||
|
Ensure the <literal>repmgr</literal> user has appropriate permissions in <filename>pg_hba.conf</filename> and
|
||||||
|
can connect in replication mode; <filename>pg_hba.conf</filename> should contain entries
|
||||||
|
similar to the following:
|
||||||
|
</para>
|
||||||
|
<programlisting>
|
||||||
|
local replication repmgr trust
|
||||||
|
host replication repmgr 127.0.0.1/32 trust
|
||||||
|
host replication repmgr 192.168.1.0/24 trust
|
||||||
|
|
||||||
|
local repmgr repmgr trust
|
||||||
|
host repmgr repmgr 127.0.0.1/32 trust
|
||||||
|
host repmgr repmgr 192.168.1.0/24 trust
|
||||||
|
</programlisting>
|
||||||
|
<para>
|
||||||
|
Note that these are simple settings for testing purposes.
|
||||||
|
Adjust according to your network environment and authentication requirements.
|
||||||
|
</para>
|
||||||
|
</sect1>
|
||||||
|
|
||||||
|
<sect1 id="quickstart-standby-preparation">
|
||||||
|
<title>Preparing the standby</title>
|
||||||
|
<para>
|
||||||
|
On the standby, do not create a PostgreSQL instance, but do ensure the destination
|
||||||
|
data directory (and any other directories which you want PostgreSQL to use)
|
||||||
|
exist and are owned by the <literal>postgres</literal> system user. Permissions
|
||||||
|
must be set to <literal>0700</literal> (<literal>drwx------</literal>).
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Check the primary database is reachable from the standby using <application>psql</application>:
|
||||||
|
</para>
|
||||||
|
<programlisting>
|
||||||
|
psql 'host=node1 user=repmgr dbname=repmgr connect_timeout=2'</programlisting>
|
||||||
|
|
||||||
|
<note>
|
||||||
|
<para>
|
||||||
|
&repmgr; stores connection information as <ulink
|
||||||
|
url="https://www.postgresql.org/docs/current/static/libpq-connect.html#LIBPQ-CONNSTRING">libpq
|
||||||
|
connection strings</ulink> throughout. This documentation refers to them as <literal>conninfo</literal>
|
||||||
|
strings; an alternative name is <literal>DSN</literal> (<literal>data source name</literal>).
|
||||||
|
We'll use these in place of the <command>-h hostname -d databasename -U username</command> syntax.
|
||||||
|
</para>
|
||||||
|
</note>
|
||||||
|
</sect1>
|
||||||
|
|
||||||
|
<sect1 id="quickstart-repmgr-conf">
|
||||||
|
<title>repmgr configuration file</title>
|
||||||
|
<para>
|
||||||
|
Create a <filename>repmgr.conf</filename> file on the primary server. The file must
|
||||||
|
contain at least the following parameters:
|
||||||
|
</para>
|
||||||
|
<programlisting>
|
||||||
|
node_id=1
|
||||||
|
node_name=node1
|
||||||
|
conninfo='host=node1 user=repmgr dbname=repmgr connect_timeout=2'
|
||||||
|
data_directory='/var/lib/postgresql/data'
|
||||||
|
</programlisting>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
<filename>repmgr.conf</filename> should not be stored inside the PostgreSQL data directory,
|
||||||
|
as it could be overwritten when setting up or reinitialising the PostgreSQL
|
||||||
|
server. See sections on <xref linkend="configuration-file"> and <xref linkend="configuration-file-settings">
|
||||||
|
for further details about <filename>repmgr.conf</filename>.
|
||||||
|
</para>
|
||||||
|
<tip>
|
||||||
|
<simpara>
|
||||||
|
For Debian-based distributions we recommend explictly setting
|
||||||
|
<literal>pg_bindir</literal> to the directory where <command>pg_ctl</command> and other binaries
|
||||||
|
not in the standard path are located. For PostgreSQL 9.6 this would be <filename>/usr/lib/postgresql/9.6/bin/</filename>.
|
||||||
|
</simpara>
|
||||||
|
</tip>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
See the file
|
||||||
|
<ulink url="https://raw.githubusercontent.com/2ndQuadrant/repmgr/master/repmgr.conf.sample">repmgr.conf.sample</>
|
||||||
|
for details of all available configuration parameters.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
</sect1>
|
||||||
|
|
||||||
|
|
||||||
|
<sect1 id="quickstart-primary-register">
|
||||||
|
<title>Register the primary server</title>
|
||||||
|
<para>
|
||||||
|
To enable &repmgr; to support a replication cluster, the primary node must
|
||||||
|
be registered with &repmgr;. This installs the <literal>repmgr</literal>
|
||||||
|
extension and metadata objects, and adds a metadata record for the primary server:
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<programlisting>
|
||||||
|
$ repmgr -f /etc/repmgr.conf primary register
|
||||||
|
INFO: connecting to primary database...
|
||||||
|
NOTICE: attempting to install extension "repmgr"
|
||||||
|
NOTICE: "repmgr" extension successfully installed
|
||||||
|
NOTICE: primary node record (id: 1) registered</programlisting>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Verify status of the cluster like this:
|
||||||
|
</para>
|
||||||
|
<programlisting>
|
||||||
|
$ repmgr -f /etc/repmgr.conf cluster show
|
||||||
|
ID | Name | Role | Status | Upstream | Connection string
|
||||||
|
----+-------+---------+-----------+----------+--------------------------------------------------------
|
||||||
|
1 | node1 | primary | * running | | host=node1 dbname=repmgr user=repmgr connect_timeout=2
|
||||||
|
</programlisting>
|
||||||
|
<para>
|
||||||
|
The record in the <literal>repmgr</literal> metadata table will look like this:
|
||||||
|
</para>
|
||||||
|
<programlisting>
|
||||||
|
repmgr=# SELECT * FROM repmgr.nodes;
|
||||||
|
-[ RECORD 1 ]----+-------------------------------------------------------
|
||||||
|
node_id | 1
|
||||||
|
upstream_node_id |
|
||||||
|
active | t
|
||||||
|
node_name | node1
|
||||||
|
type | primary
|
||||||
|
location | default
|
||||||
|
priority | 100
|
||||||
|
conninfo | host=node1 dbname=repmgr user=repmgr connect_timeout=2
|
||||||
|
repluser | repmgr
|
||||||
|
slot_name |
|
||||||
|
config_file | /etc/repmgr.conf</programlisting>
|
||||||
|
<para>
|
||||||
|
Each server in the replication cluster will have its own record. If <command>repmgrd</command>
|
||||||
|
is in use, the fields <literal>upstream_node_id</literal>, <literal>active</literal> and
|
||||||
|
<literal>type</literal> will be updated when the node's status or role changes.
|
||||||
|
</para>
|
||||||
|
</sect1>
|
||||||
|
|
||||||
|
<sect1 id="quickstart-standby-clone">
|
||||||
|
<title>Clone the standby server</title>
|
||||||
|
<para>
|
||||||
|
Create a <filename>repmgr.conf</filename> file on the standby server. It must contain at
|
||||||
|
least the same parameters as the primary's <filename>repmgr.conf</filename>, but with
|
||||||
|
the mandatory values <literal>node</literal>, <literal>node_name</literal>, <literal>conninfo</literal>
|
||||||
|
(and possibly <literal>data_directory</literal>) adjusted accordingly, e.g.:
|
||||||
|
</para>
|
||||||
|
<programlisting>
|
||||||
|
node=2
|
||||||
|
node_name=node2
|
||||||
|
conninfo='host=node2 user=repmgr dbname=repmgr connect_timeout=2'
|
||||||
|
data_directory='/var/lib/postgresql/data'
|
||||||
|
</programlisting>
|
||||||
|
<para>
|
||||||
|
Use the <command>--dry-run</command> option to check the standby can be cloned:
|
||||||
|
</para>
|
||||||
|
<programlisting>
|
||||||
|
$ repmgr -h node1 -U repmgr -d repmgr -f /etc/repmgr.conf standby clone --dry-run
|
||||||
|
NOTICE: using provided configuration file "/etc/repmgr.conf"
|
||||||
|
NOTICE: destination directory "/var/lib/postgresql/data" provided
|
||||||
|
INFO: connecting to source node
|
||||||
|
NOTICE: checking for available walsenders on source node (2 required)
|
||||||
|
INFO: sufficient walsenders available on source node (2 required)
|
||||||
|
NOTICE: standby will attach to upstream node 1
|
||||||
|
HINT: consider using the -c/--fast-checkpoint option
|
||||||
|
INFO: all prerequisites for "standby clone" are met</programlisting>
|
||||||
|
<para>
|
||||||
|
If no problems are reported, the standby can then be cloned with:
|
||||||
|
</para>
|
||||||
|
<programlisting>
|
||||||
|
$ repmgr -h node1 -U repmgr -d repmgr -f /etc/repmgr.conf standby clone
|
||||||
|
|
||||||
|
NOTICE: using configuration file "/etc/repmgr.conf"
|
||||||
|
NOTICE: destination directory "/var/lib/postgresql/data" provided
|
||||||
|
INFO: connecting to source node
|
||||||
|
NOTICE: checking for available walsenders on source node (2 required)
|
||||||
|
INFO: sufficient walsenders available on source node (2 required)
|
||||||
|
INFO: creating directory "/var/lib/postgresql/data"...
|
||||||
|
NOTICE: starting backup (using pg_basebackup)...
|
||||||
|
HINT: this may take some time; consider using the -c/--fast-checkpoint option
|
||||||
|
INFO: executing:
|
||||||
|
pg_basebackup -l "repmgr base backup" -D /var/lib/postgresql/data -h node1 -U repmgr -X stream
|
||||||
|
NOTICE: standby clone (using pg_basebackup) complete
|
||||||
|
NOTICE: you can now start your PostgreSQL server
|
||||||
|
HINT: for example: pg_ctl -D /var/lib/postgresql/data start
|
||||||
|
</programlisting>
|
||||||
|
<para>
|
||||||
|
This has cloned the PostgreSQL data directory files from the primary <literal>node1</literal>
|
||||||
|
using PostgreSQL's <command>pg_basebackup</command> utility. A <filename>recovery.conf</filename>
|
||||||
|
file containing the correct parameters to start streaming from this primary server will be created
|
||||||
|
automatically.
|
||||||
|
</para>
|
||||||
|
<note>
|
||||||
|
<simpara>
|
||||||
|
By default, any configuration files in the primary's data directory will be
|
||||||
|
copied to the standby. Typically these will be <filename>postgresql.conf</filename>,
|
||||||
|
<filename>postgresql.auto.conf</filename>, <filename>pg_hba.conf</filename> and
|
||||||
|
<filename>pg_ident.conf</filename>. These may require modification before the standby
|
||||||
|
is started.
|
||||||
|
</simpara>
|
||||||
|
</note>
|
||||||
|
<para>
|
||||||
|
Make any adjustments to the standby's PostgreSQL configuration files now,
|
||||||
|
then start the server.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
For more details on <command>repmgr standby clone</command>, see the
|
||||||
|
<link linkend="repmgr-standby-clone">command reference</link>.
|
||||||
|
A more detailed overview of cloning options is available in the
|
||||||
|
<link linkend="cloning-standbys">administration manual</link>.
|
||||||
|
</para>
|
||||||
|
</sect1>
|
||||||
|
|
||||||
|
<sect1 id="quickstart-verify-replication">
|
||||||
|
<title>Verify replication is functioning</title>
|
||||||
|
<para>
|
||||||
|
Connect to the primary server and execute:
|
||||||
|
<programlisting>
|
||||||
|
repmgr=# SELECT * FROM pg_stat_replication;
|
||||||
|
-[ RECORD 1 ]----+------------------------------
|
||||||
|
pid | 19111
|
||||||
|
usesysid | 16384
|
||||||
|
usename | repmgr
|
||||||
|
application_name | node2
|
||||||
|
client_addr | 192.168.1.12
|
||||||
|
client_hostname |
|
||||||
|
client_port | 50378
|
||||||
|
backend_start | 2017-08-28 15:14:19.851581+09
|
||||||
|
backend_xmin |
|
||||||
|
state | streaming
|
||||||
|
sent_location | 0/7000318
|
||||||
|
write_location | 0/7000318
|
||||||
|
flush_location | 0/7000318
|
||||||
|
replay_location | 0/7000318
|
||||||
|
sync_priority | 0
|
||||||
|
sync_state | async</programlisting>
|
||||||
|
This shows that the previously cloned standby (<literal>node2</literal> shown in the field
|
||||||
|
<literal>application_name</literal>) has connected to the primary from IP address
|
||||||
|
<literal>192.168.1.12</literal>.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
From PostgreSQL 9.6 you can also use the view
|
||||||
|
<ulink url="https://www.postgresql.org/docs/current/static/monitoring-stats.html#PG-STAT-WAL-RECEIVER-VIEW">
|
||||||
|
<literal>pg_stat_wal_receiver</literal></ulink> to check the replication status from the standby.
|
||||||
|
|
||||||
|
<programlisting>
|
||||||
|
repmgr=# SELECT * FROM pg_stat_wal_receiver;
|
||||||
|
Expanded display is on.
|
||||||
|
-[ RECORD 1 ]---------+--------------------------------------------------------------------------------
|
||||||
|
pid | 18236
|
||||||
|
status | streaming
|
||||||
|
receive_start_lsn | 0/3000000
|
||||||
|
receive_start_tli | 1
|
||||||
|
received_lsn | 0/7000538
|
||||||
|
received_tli | 1
|
||||||
|
last_msg_send_time | 2017-08-28 15:21:26.465728+09
|
||||||
|
last_msg_receipt_time | 2017-08-28 15:21:26.465774+09
|
||||||
|
latest_end_lsn | 0/7000538
|
||||||
|
latest_end_time | 2017-08-28 15:20:56.418735+09
|
||||||
|
slot_name |
|
||||||
|
conninfo | user=repmgr dbname=replication host=node1 application_name=node2
|
||||||
|
</programlisting>
|
||||||
|
Note that the <varname>conninfo</varname> value is that generated in <filename>recovery.conf</filename>
|
||||||
|
and will differ slightly from the primary's <varname>conninfo</varname> as set in <filename>repmgr.conf</filename> -
|
||||||
|
among others it will contain the connecting node's name as <varname>application_name</varname>.
|
||||||
|
</para>
|
||||||
|
</sect1>
|
||||||
|
|
||||||
|
<sect1 id="quickstart-register-standby">
|
||||||
|
<title>Register the standby</title>
|
||||||
|
<para>
|
||||||
|
Register the standby server with:
|
||||||
|
<programlisting>
|
||||||
|
$ repmgr -f /etc/repmgr.conf standby register
|
||||||
|
NOTICE: standby node "node2" (ID: 2) successfully registered</programlisting>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Check the node is registered by executing <command>repmgr cluster show</command> on the standby:
|
||||||
|
<programlisting>
|
||||||
|
$ repmgr -f /etc/repmgr.conf cluster show
|
||||||
|
ID | Name | Role | Status | Upstream | Location | Connection string
|
||||||
|
----+-------+---------+-----------+----------+----------+--------------------------------------
|
||||||
|
1 | node1 | primary | * running | | default | host=node1 dbname=repmgr user=repmgr
|
||||||
|
2 | node2 | standby | running | node1 | default | host=node2 dbname=repmgr user=repmgr</programlisting>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Both nodes are now registered with &repmgr; and the records have been copied to the standby server.
|
||||||
|
</para>
|
||||||
|
</sect1>
|
||||||
|
|
||||||
|
</chapter>
|
||||||
23
doc/repmgr-cluster-cleanup.sgml
Normal file
23
doc/repmgr-cluster-cleanup.sgml
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
<chapter id="repmgr-cluster-cleanup" xreflabel="repmgr cluster cleanup">
|
||||||
|
<indexterm>
|
||||||
|
<primary>repmgr cluster cleanup</primary>
|
||||||
|
</indexterm>
|
||||||
|
<title>repmgr cluster cleanup</title>
|
||||||
|
<para>
|
||||||
|
Purges monitoring history from the <literal>repmgr.monitoring_history</literal> table to
|
||||||
|
prevent excessive table growth. Use the <literal>-k/--keep-history</literal> to specify the
|
||||||
|
number of days of monitoring history to retain. This command can be used
|
||||||
|
manually or as a cronjob.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
This command requires a valid <filename>repmgr.conf</filename> file for the node on which it is
|
||||||
|
executed; no additional arguments are required.
|
||||||
|
</para>
|
||||||
|
<note>
|
||||||
|
<simpara>
|
||||||
|
Monitoring history will only be written if <command>repmgrd</command> is active, and
|
||||||
|
<varname>monitoring_history</varname> is set to <literal>true</literal> in
|
||||||
|
<filename>repmgr.conf</filename>.
|
||||||
|
</simpara>
|
||||||
|
</note>
|
||||||
|
</chapter>
|
||||||
28
doc/repmgr-cluster-crosscheck.sgml
Normal file
28
doc/repmgr-cluster-crosscheck.sgml
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
<chapter id="repmgr-cluster-crosscheck" xreflabel="repmgr cluster crosscheck">
|
||||||
|
<indexterm>
|
||||||
|
<primary>repmgr cluster crosscheck</primary>
|
||||||
|
</indexterm>
|
||||||
|
<title>repmgr cluster crosscheck</title>
|
||||||
|
<para>
|
||||||
|
<command>repmgr cluster crosscheck</command> is similar to <xref linkend="repmgr-cluster-matrix">,
|
||||||
|
but cross-checks connections between each combination of nodes. In "Example 3" in
|
||||||
|
<xref linkend="repmgr-cluster-matrix"> we have no information about the state of <literal>node3</literal>.
|
||||||
|
However by running <command>repmgr cluster crosscheck</command> it's possible to get a better
|
||||||
|
overview of the cluster situation:
|
||||||
|
<programlisting>
|
||||||
|
$ repmgr -f /etc/repmgr.conf cluster crosscheck
|
||||||
|
|
||||||
|
Name | Id | 1 | 2 | 3
|
||||||
|
-------+----+----+----+----
|
||||||
|
node1 | 1 | * | * | x
|
||||||
|
node2 | 2 | * | * | *
|
||||||
|
node3 | 3 | * | * | *</programlisting>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
What happened is that <command>repmgr cluster crosscheck</command> merged its own
|
||||||
|
<command>repmgr cluster matrix</command> with the <command>repmgr cluster matrix</command>
|
||||||
|
output from <literal>node2</literal>; the latter is able to connect to <literal>node3</literal>
|
||||||
|
and therefore determine the state of outbound connections from that node.
|
||||||
|
</para>
|
||||||
|
</chapter>
|
||||||
|
|
||||||
37
doc/repmgr-cluster-event.sgml
Normal file
37
doc/repmgr-cluster-event.sgml
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
<chapter id="repmgr-cluster-event" xreflabel="repmgr cluster event">
|
||||||
|
<indexterm>
|
||||||
|
<primary>repmgr cluster event</primary>
|
||||||
|
</indexterm>
|
||||||
|
<title>repmgr cluster event</title>
|
||||||
|
<para>
|
||||||
|
This outputs a formatted list of cluster events, as stored in the
|
||||||
|
<literal>repmgr.events</literal> table. Output is in reverse chronological order, and
|
||||||
|
can be filtered with the following options:
|
||||||
|
<itemizedlist spacing="compact" mark="bullet">
|
||||||
|
<listitem>
|
||||||
|
<simpara><literal>--all</literal>: outputs all entries</simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara><literal>--limit</literal>: set the maximum number of entries to output (default: 20)</simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara><literal>--node-id</literal>: restrict entries to node with this ID</simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara><literal>--node-name</literal>: restrict entries to node with this name</simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara><literal>--event</literal>: filter specific event</simpara>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Example:
|
||||||
|
<programlisting>
|
||||||
|
$ repmgr -f /etc/repmgr.conf cluster event --event=standby_register
|
||||||
|
Node ID | Name | Event | OK | Timestamp | Details
|
||||||
|
---------+-------+------------------+----+---------------------+--------------------------------
|
||||||
|
3 | node3 | standby_register | t | 2017-08-17 10:28:55 | standby registration succeeded
|
||||||
|
2 | node2 | standby_register | t | 2017-08-17 10:28:53 | standby registration succeeded</programlisting>
|
||||||
|
</para>
|
||||||
|
</chapter>
|
||||||
83
doc/repmgr-cluster-matrix.sgml
Normal file
83
doc/repmgr-cluster-matrix.sgml
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
<chapter id="repmgr-cluster-matrix" xreflabel="repmgr cluster matrix">
|
||||||
|
<indexterm>
|
||||||
|
<primary>repmgr cluster matrix</primary>
|
||||||
|
</indexterm>
|
||||||
|
<title>repmgr cluster matrix</title>
|
||||||
|
<para>
|
||||||
|
<command>repmgr cluster matrix</command> runs <command>repmgr cluster show</command> on each
|
||||||
|
node and arranges the results in a matrix, recording success or failure.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
<command>repmgr cluster matrix</command> requires a valid <filename>repmgr.conf</filename>
|
||||||
|
file on each node. Additionally passwordless `ssh` connections are required between
|
||||||
|
all nodes.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Example 1 (all nodes up):
|
||||||
|
<programlisting>
|
||||||
|
$ repmgr -f /etc/repmgr.conf cluster matrix
|
||||||
|
|
||||||
|
Name | Id | 1 | 2 | 3
|
||||||
|
-------+----+----+----+----
|
||||||
|
node1 | 1 | * | * | *
|
||||||
|
node2 | 2 | * | * | *
|
||||||
|
node3 | 3 | * | * | *</programlisting>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Example 2 (<literal>node1</literal> and <literal>node2</literal> up, <literal>node3</literal> down):
|
||||||
|
<programlisting>
|
||||||
|
$ repmgr -f /etc/repmgr.conf cluster matrix
|
||||||
|
|
||||||
|
Name | Id | 1 | 2 | 3
|
||||||
|
-------+----+----+----+----
|
||||||
|
node1 | 1 | * | * | x
|
||||||
|
node2 | 2 | * | * | x
|
||||||
|
node3 | 3 | ? | ? | ?
|
||||||
|
</programlisting>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Each row corresponds to one server, and indicates the result of
|
||||||
|
testing an outbound connection from that server.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Since <literal>node3</literal> is down, all the entries in its row are filled with
|
||||||
|
<literal>?</literal>, meaning that there we cannot test outbound connections.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The other two nodes are up; the corresponding rows have <literal>x</literal> in the
|
||||||
|
column corresponding to <literal>node3</literal>, meaning that inbound connections to
|
||||||
|
that node have failed, and `*` in the columns corresponding to
|
||||||
|
<literal>node1</literal> and <literal>node2</literal>, meaning that inbound connections
|
||||||
|
to these nodes have succeeded.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Example 3 (all nodes up, firewall dropping packets originating
|
||||||
|
from <literal>node1</literal> and directed to port 5432 on <literal>node3</literal>) -
|
||||||
|
running <command>repmgr cluster matrix</command> from <literal>node1</literal> gives the following output:
|
||||||
|
<programlisting>
|
||||||
|
$ repmgr -f /etc/repmgr.conf cluster matrix
|
||||||
|
|
||||||
|
Name | Id | 1 | 2 | 3
|
||||||
|
-------+----+----+----+----
|
||||||
|
node1 | 1 | * | * | x
|
||||||
|
node2 | 2 | * | * | *
|
||||||
|
node3 | 3 | ? | ? | ?</programlisting>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Note this may take some time depending on the <varname>connect_timeout</varname>
|
||||||
|
setting in the node <varname>conninfo</varname> strings; default is
|
||||||
|
<literal>1 minute</literal> which means without modification the above
|
||||||
|
command would take around 2 minutes to run; see comment elsewhere about setting
|
||||||
|
<varname>connect_timeout</varname>)
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The matrix tells us that we cannot connect from <literal>node1</literal> to <literal>node3</literal>,
|
||||||
|
and that (therefore) we don't know the state of any outbound
|
||||||
|
connection from <literal>node3</literal>.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
In this case, the <xref linkend="repmgr-cluster-crosscheck"> command will produce a more
|
||||||
|
useful result.
|
||||||
|
</para>
|
||||||
|
</chapter>
|
||||||
|
|
||||||
67
doc/repmgr-cluster-show.sgml
Normal file
67
doc/repmgr-cluster-show.sgml
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
<chapter id="repmgr-cluster-show" xreflabel="repmgr cluster show">
|
||||||
|
<indexterm>
|
||||||
|
<primary>repmgr cluster show</primary>
|
||||||
|
</indexterm>
|
||||||
|
<title>repmgr cluster show</title>
|
||||||
|
<para>
|
||||||
|
Displays information about each active node in the replication cluster. This
|
||||||
|
command polls each registered server and shows its role (<literal>primary</literal> /
|
||||||
|
<literal>standby</literal> / <literal>bdr</literal>) and status. It polls each server
|
||||||
|
directly and can be run on any node in the cluster; this is also useful when analyzing
|
||||||
|
connectivity from a particular node.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
This command requires either a valid <filename>repmgr.conf</filename> file or a database
|
||||||
|
connection string to one of the registered nodes; no additional arguments are needed.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Example:
|
||||||
|
<programlisting>
|
||||||
|
$ repmgr -f /etc/repmgr.conf cluster show
|
||||||
|
|
||||||
|
ID | Name | Role | Status | Upstream | Location | Connection string
|
||||||
|
----+-------+---------+-----------+----------+----------+-----------------------------------------
|
||||||
|
1 | node1 | primary | * running | | default | host=db_node1 dbname=repmgr user=repmgr
|
||||||
|
2 | node2 | standby | running | node1 | default | host=db_node2 dbname=repmgr user=repmgr
|
||||||
|
3 | node3 | standby | running | node1 | default | host=db_node3 dbname=repmgr user=repmgr</programlisting>
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
To show database connection errors when polling nodes, run the command in
|
||||||
|
<literal>--verbose</literal> mode.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The `cluster show` command accepts an optional parameter <literal>--csv</literal>, which
|
||||||
|
outputs the replication cluster's status in a simple CSV format, suitable for
|
||||||
|
parsing by scripts:
|
||||||
|
<programlisting>
|
||||||
|
$ repmgr -f /etc/repmgr.conf cluster show --csv
|
||||||
|
1,-1,-1
|
||||||
|
2,0,0
|
||||||
|
3,0,1</programlisting>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The columns have following meanings:
|
||||||
|
<itemizedlist spacing="compact" mark="bullet">
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
node ID
|
||||||
|
</simpara>
|
||||||
|
<simpara>
|
||||||
|
availability (0 = available, -1 = unavailable)
|
||||||
|
</simpara>
|
||||||
|
<simpara>
|
||||||
|
recovery state (0 = not in recovery, 1 = in recovery, -1 = unknown)
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Note that the availability is tested by connecting from the node where
|
||||||
|
<command>repmgr cluster show</command> is executed, and does not necessarily imply the node
|
||||||
|
is down. See <xref linkend="repmgr-cluster-matrix"> and <xref linkend="repmgr-cluster-crosscheck"> to get
|
||||||
|
a better overviews of connections between nodes.
|
||||||
|
</para>
|
||||||
|
</chapter>
|
||||||
70
doc/repmgr-node-check.sgml
Normal file
70
doc/repmgr-node-check.sgml
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
<chapter id="repmgr-node-check" xreflabel="repmgr node check">
|
||||||
|
<indexterm>
|
||||||
|
<primary>repmgr node check</primary>
|
||||||
|
</indexterm>
|
||||||
|
<title>repmgr node check</title>
|
||||||
|
<para>
|
||||||
|
Performs some health checks on a node from a replication perspective.
|
||||||
|
This command must be run on the local node.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Sample output (execute <command>repmgr node check</command>):
|
||||||
|
<programlisting>
|
||||||
|
Node "node1":
|
||||||
|
Server role: OK (node is primary)
|
||||||
|
Replication lag: OK (N/A - node is primary)
|
||||||
|
WAL archiving: OK (0 pending files)
|
||||||
|
Downstream servers: OK (2 of 2 downstream nodes attached)
|
||||||
|
Replication slots: OK (node has no replication slots)
|
||||||
|
</programlisting>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Additionally each check can be performed individually by supplying
|
||||||
|
an additional command line parameter, e.g.:
|
||||||
|
<programlisting>
|
||||||
|
$ repmgr node check --role
|
||||||
|
OK (node is primary)
|
||||||
|
</programlisting>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Parameters for individual checks are as follows:
|
||||||
|
<itemizedlist spacing="compact" mark="bullet">
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
<literal>--role</literal>: checks if the node has the expected role
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
<literal>--replication-lag</literal>: checks if the node is lagging by more than
|
||||||
|
<varname>replication_lag_warning</varname> or <varname>replication_lag_critical</varname>
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
<literal>--archive-ready</literal>: checks for WAL files which have not yet been archived
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
<literal>--downstream</literal>: checks that the expected downstream nodes are attached
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
<literal>--slots</literal>: checks there are no inactive replication slots
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
</itemizedlist>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Individual checks can also be output in a Nagios-compatible format by additionally
|
||||||
|
providing the option <literal>--nagios</literal>.
|
||||||
|
</para>
|
||||||
|
</chapter>
|
||||||
13
doc/repmgr-node-rejoin.sgml
Normal file
13
doc/repmgr-node-rejoin.sgml
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<chapter id="repmgr-node-rejoin" xreflabel="repmgr node rejoin">
|
||||||
|
<indexterm>
|
||||||
|
<primary>repmgr node rejoin</primary>
|
||||||
|
</indexterm>
|
||||||
|
<title>repmgr node rejoin</title>
|
||||||
|
<para>
|
||||||
|
Enables a dormant (stopped) node to be rejoined to the replication cluster.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
This can optionally use <command>pg_rewind</command> to re-integrate a node which has diverged
|
||||||
|
from the rest of the cluster, typically a failed primary.
|
||||||
|
</para>
|
||||||
|
</chapter>
|
||||||
29
doc/repmgr-node-status.sgml
Normal file
29
doc/repmgr-node-status.sgml
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
|
||||||
|
<chapter id="repmgr-node-status" xreflabel="repmgr node status">
|
||||||
|
<indexterm>
|
||||||
|
<primary>repmgr node status</primary>
|
||||||
|
</indexterm>
|
||||||
|
<title>repmgr node status</title>
|
||||||
|
<para>
|
||||||
|
Displays an overview of a node's basic information and replication
|
||||||
|
status. This command must be run on the local node.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Sample output (execute <command>repmgr node status</command>):
|
||||||
|
<programlisting>
|
||||||
|
Node "node1":
|
||||||
|
PostgreSQL version: 10beta1
|
||||||
|
Total data size: 30 MB
|
||||||
|
Conninfo: host=node1 dbname=repmgr user=repmgr connect_timeout=2
|
||||||
|
Role: primary
|
||||||
|
WAL archiving: off
|
||||||
|
Archive command: (none)
|
||||||
|
Replication connections: 2 (of maximal 10)
|
||||||
|
Replication slots: 0 (of maximal 10)
|
||||||
|
Replication lag: n/a
|
||||||
|
</programlisting>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
See <xref linkend="repmgr-node-check"> to diagnose issues.
|
||||||
|
</para>
|
||||||
|
</chapter>
|
||||||
18
doc/repmgr-primary-register.sgml
Normal file
18
doc/repmgr-primary-register.sgml
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<chapter id="repmgr-primary-register" xreflabel="repmgr primary register">
|
||||||
|
<indexterm><primary>repmgr primary register</primary></indexterm>
|
||||||
|
<title>repmgr primary register</title>
|
||||||
|
<para>
|
||||||
|
<command>repmgr primary register</command> registers a primary node in a
|
||||||
|
streaming replication cluster, and configures it for use with repmgr, including
|
||||||
|
installing the &repmgr; extension. This command needs to be executed before any
|
||||||
|
standby nodes are registered.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Execute with the <literal>--dry-run</literal> option to check what would happen without
|
||||||
|
actually registering the primary.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
<command>repmgr master register</command> can be used as an alias for
|
||||||
|
<command>repmgr primary register</command>.
|
||||||
|
</para>
|
||||||
|
</chapter>
|
||||||
18
doc/repmgr-primary-unregister.sgml
Normal file
18
doc/repmgr-primary-unregister.sgml
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<chapter id="repmgr-primary-unregister" xreflabel="repmgr primary unregister">
|
||||||
|
<indexterm><primary>repmgr primary unregister</primary></indexterm>
|
||||||
|
<title>repmgr primary unregister</title>
|
||||||
|
<para>
|
||||||
|
<command>repmgr primary register</command> unregisters an inactive primary node
|
||||||
|
from the &repmgr; metadata. This is typically when the primary has failed and is
|
||||||
|
being removed from the cluster after a new primary has been promoted.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Execute with the <literal>--dry-run</literal> option to check what would happen without
|
||||||
|
actually unregistering the node.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
<command>repmgr master unregister</command> can be used as an alias for
|
||||||
|
<command>repmgr primary unregister</command>/
|
||||||
|
</para>
|
||||||
|
</chapter>
|
||||||
91
doc/repmgr-standby-clone.sgml
Normal file
91
doc/repmgr-standby-clone.sgml
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
<chapter id="repmgr-standby-clone" xreflabel="repmgr standby clone">
|
||||||
|
<indexterm>
|
||||||
|
<primary>repmgr standby clone</primary>
|
||||||
|
<seealso>cloning</seealso>
|
||||||
|
</indexterm>
|
||||||
|
<title>repmgr standby clone</title>
|
||||||
|
<para>
|
||||||
|
<command>repmgr standby clone</command> clones a PostgreSQL node from another
|
||||||
|
PostgreSQL node, typically the primary, but optionally from any other node in
|
||||||
|
the cluster or from Barman. It creates the <filename>recovery.conf</filename> file required
|
||||||
|
to attach the cloned node to the primary node (or another standby, if cascading replication
|
||||||
|
is in use).
|
||||||
|
</para>
|
||||||
|
<note>
|
||||||
|
<simpara>
|
||||||
|
<command>repmgr standby clone</command> does not start the standby, and after cloning
|
||||||
|
<command>repmgr standby register</command> must be executed to notify &repmgr; of its presence.
|
||||||
|
</simpara>
|
||||||
|
</note>
|
||||||
|
|
||||||
|
|
||||||
|
<sect1 id="repmgr-standby-clone-config-file-copying" xreflabel="Copying configuration files">
|
||||||
|
<title>Handling configuration files</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Note that by default, all configuration files in the source node's data
|
||||||
|
directory will be copied to the cloned node. Typically these will be
|
||||||
|
<filename>postgresql.conf</filename>, <filename>postgresql.auto.conf</filename>,
|
||||||
|
<filename>pg_hba.conf</filename> and <filename>pg_ident.conf</filename>.
|
||||||
|
These may require modification before the standby is started.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
In some cases (e.g. on Debian or Ubuntu Linux installations), PostgreSQL's
|
||||||
|
configuration files are located outside of the data directory and will
|
||||||
|
not be copied by default. &repmgr; can copy these files, either to the same
|
||||||
|
location on the standby server (provided appropriate directory and file permissions
|
||||||
|
are available), or into the standby's data directory. This requires passwordless
|
||||||
|
SSH access to the primary server. Add the option <literal>--copy-external-config-files</literal>
|
||||||
|
to the <command>repmgr standby clone</command> command; by default files will be copied to
|
||||||
|
the same path as on the upstream server. Note that the user executing <command>repmgr</command>
|
||||||
|
must have write access to those directories.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
To have the configuration files placed in the standby's data directory, specify
|
||||||
|
<literal>--copy-external-config-files=pgdata</literal>, but note that
|
||||||
|
any include directives in the copied files may need to be updated.
|
||||||
|
</para>
|
||||||
|
<tip>
|
||||||
|
<simpara>
|
||||||
|
For reliable configuration file management we recommend using a
|
||||||
|
configuration management tool such as Ansible, Chef, Puppet or Salt.
|
||||||
|
</simpara>
|
||||||
|
</tip>
|
||||||
|
</sect1>
|
||||||
|
|
||||||
|
<sect1 id="repmgr-standby-clone-wal-management" xreflabel="Managing WAL during the cloning process">
|
||||||
|
<title>Managing WAL during the cloning process</title>
|
||||||
|
<para>
|
||||||
|
When initially cloning a standby, you will need to ensure
|
||||||
|
that all required WAL files remain available while the cloning is taking
|
||||||
|
place. To ensure this happens when using the default `pg_basebackup` method,
|
||||||
|
&repmgr; will set <command>pg_basebackup</command>'s <literal>--xlog-method</literal>
|
||||||
|
parameter to <literal>stream</literal>,
|
||||||
|
which will ensure all WAL files generated during the cloning process are
|
||||||
|
streamed in parallel with the main backup. Note that this requires two
|
||||||
|
replication connections to be available (&repmgr; will verify sufficient
|
||||||
|
connections are available before attempting to clone, and this can be checked
|
||||||
|
before performing the clone using the <literal>--dry-run</literal> option).
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
To override this behaviour, in <filename>repmgr.conf</filename> set
|
||||||
|
<command>pg_basebackup</command>'s <literal>--xlog-method</literal>
|
||||||
|
parameter to <literal>fetch</literal>:
|
||||||
|
<programlisting>
|
||||||
|
pg_basebackup_options='--xlog-method=fetch'</programlisting>
|
||||||
|
|
||||||
|
and ensure that <literal>wal_keep_segments</literal> is set to an appropriately high value.
|
||||||
|
See the <ulink url="https://www.postgresql.org/docs/current/static/app-pgbasebackup.html">
|
||||||
|
pg_basebackup</ulink> documentation for details.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<note>
|
||||||
|
<simpara>
|
||||||
|
From PostgreSQL 10, <command>pg_basebackup</command>'s
|
||||||
|
<literal>--xlog-method</literal> parameter has been renamed to
|
||||||
|
<literal>--wal-method</literal>.
|
||||||
|
</simpara>
|
||||||
|
</note>
|
||||||
|
</sect1>
|
||||||
|
</chapter>
|
||||||
|
|
||||||
21
doc/repmgr-standby-follow.sgml
Normal file
21
doc/repmgr-standby-follow.sgml
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
<chapter id="repmgr-standby-follow" xreflabel="repmgr standby follow">
|
||||||
|
<indexterm>
|
||||||
|
<primary>repmgr standby follow</primary>
|
||||||
|
</indexterm>
|
||||||
|
<title>repmgr standby follow</title>
|
||||||
|
<para>
|
||||||
|
Attaches the standby to a new primary. This command requires a valid
|
||||||
|
<filename>repmgr.conf</filename> file for the standby, either specified
|
||||||
|
explicitly with <literal>-f/--config-file</literal> or located in a
|
||||||
|
default location; no additional arguments are required.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
This command will force a restart of the standby server, which must be
|
||||||
|
running. It can only be used to attach a standby to a new primary node.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
To re-add an inactive node to the replication cluster, see
|
||||||
|
<xref linkend="repmgr-node-rejoin">
|
||||||
|
</para>
|
||||||
|
</chapter>
|
||||||
|
|
||||||
18
doc/repmgr-standby-promote.sgml
Normal file
18
doc/repmgr-standby-promote.sgml
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<chapter id="repmgr-standby-promote" xreflabel="repmgr standby promote">
|
||||||
|
<indexterm>
|
||||||
|
<primary>repmgr standby promote</primary>
|
||||||
|
</indexterm>
|
||||||
|
<title>repmgr standby promote</title>
|
||||||
|
<para>
|
||||||
|
Promotes a standby to a primary if the current primary has failed. This
|
||||||
|
command requires a valid <filename>repmgr.conf</filename> file for the standby, either
|
||||||
|
specified explicitly with <literal>-f/--config-file</literal> or located in a
|
||||||
|
default location; no additional arguments are required.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
If the standby promotion succeeds, the server will not need to be
|
||||||
|
restarted. However any other standbys will need to follow the new server,
|
||||||
|
by using <xref linkend="repmgr-standby-follow">; if <command>repmgrd</command>
|
||||||
|
is active, it will handle this automatically.
|
||||||
|
</para>
|
||||||
|
</chapter>
|
||||||
50
doc/repmgr-standby-register.sgml
Normal file
50
doc/repmgr-standby-register.sgml
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
<chapter id="repmgr-standby-register" xreflabel="repmgr standby register">
|
||||||
|
<indexterm><primary>repmgr standby register</primary></indexterm>
|
||||||
|
<title>repmgr standby register</title>
|
||||||
|
<para>
|
||||||
|
<command>repmgr standby register</command> adds a standby's information to
|
||||||
|
the &repmgr; metadata. This command needs to be executed to enable
|
||||||
|
promote/follow operations and to allow <command>repmgrd</command> to work with the node.
|
||||||
|
An existing standby can be registered using this command. Execute with the
|
||||||
|
<literal>--dry-run</literal> option to check what would happen without actually registering the
|
||||||
|
standby.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<sect1 id="repmgr-standby-register-wait" xreflabel="repmgr standby register --wait">
|
||||||
|
<title>Waiting for the registration to propagate to the standby</title>
|
||||||
|
<para>
|
||||||
|
Depending on your environment and workload, it may take some time for
|
||||||
|
the standby's node record to propagate from the primary to the standby. Some
|
||||||
|
actions (such as starting <command>repmgrd</command>) require that the standby's node record
|
||||||
|
is present and up-to-date to function correctly.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
By providing the option <literal>--wait-sync</literal> to the
|
||||||
|
<command>repmgr standby register</command> command, &repmgr; will wait
|
||||||
|
until the record is synchronised before exiting. An optional timeout (in
|
||||||
|
seconds) can be added to this option (e.g. <literal>--wait-sync=60</literal>).
|
||||||
|
</para>
|
||||||
|
</sect1>
|
||||||
|
|
||||||
|
<sect1 id="rempgr-standby-register-inactive-node" xreflabel="Registering an inactive node">
|
||||||
|
<title>Registering an inactive node</title>
|
||||||
|
<para>
|
||||||
|
Under some circumstances you may wish to register a standby which is not
|
||||||
|
yet running; this can be the case when using provisioning tools to create
|
||||||
|
a complex replication cluster. In this case, by using the <literal>-F/--force</literal>
|
||||||
|
option and providing the connection parameters to the primary server,
|
||||||
|
the standby can be registered.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Similarly, with cascading replication it may be necessary to register
|
||||||
|
a standby whose upstream node has not yet been registered - in this case,
|
||||||
|
using <literal>-F/--force</literal> will result in the creation of an inactive placeholder
|
||||||
|
record for the upstream node, which will however later need to be registered
|
||||||
|
with the <literal>-F/--force</literal> option too.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
When used with <command>repmgr standby register</command>, care should be taken that use of the
|
||||||
|
<literal>-F/--force</literal> option does not result in an incorrectly configured cluster.
|
||||||
|
</para>
|
||||||
|
</sect1>
|
||||||
|
</chapter>
|
||||||
27
doc/repmgr-standby-switchover.sgml
Normal file
27
doc/repmgr-standby-switchover.sgml
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
<chapter id="repmgr-standby-switchover" xreflabel="repmgr standby switchover">
|
||||||
|
<indexterm>
|
||||||
|
<primary>repmgr standby switchover</primary>
|
||||||
|
</indexterm>
|
||||||
|
<title>repmgr standby switchover</title>
|
||||||
|
<para>
|
||||||
|
Promotes a standby to primary and demotes the existing primary to a standby.
|
||||||
|
This command must be run on the standby to be promoted, and requires a
|
||||||
|
passwordless SSH connection to the current primary.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
If other standbys are connected to the demotion candidate, &repmgr; can instruct
|
||||||
|
these to follow the new primary if the option <literal>--siblings-follow</literal>
|
||||||
|
is specified.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Execute with the <literal>--dry-run</literal> option to test the switchover as far as
|
||||||
|
possible without actually changing the status of either node.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
<command>repmgrd</command> should not be active on any nodes while a switchover is being
|
||||||
|
executed. This restriction may be lifted in a later version.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
For more details see the section <xref linkend="performing-switchover">.
|
||||||
|
</para>
|
||||||
|
</chapter>
|
||||||
29
doc/repmgr-standby-unregister.sgml
Normal file
29
doc/repmgr-standby-unregister.sgml
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
<chapter id="repmgr-standby-unregister" xreflabel="repmgr standby unregister">
|
||||||
|
<indexterm><primary>repmgr standby unregister</primary></indexterm>
|
||||||
|
<title>repmgr standby unregister</title>
|
||||||
|
<para>
|
||||||
|
Unregisters a standby with `repmgr`. This command does not affect the actual
|
||||||
|
replication, just removes the standby's entry from the &repmgr; metadata.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
To unregister a running standby, execute:
|
||||||
|
<programlisting>
|
||||||
|
repmgr standby unregister -f /etc/repmgr.conf</programlisting>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
This will remove the standby record from &repmgr;'s internal metadata
|
||||||
|
table (<literal>repmgr.nodes</literal>). A <literal>standby_unregister</literal>
|
||||||
|
event notification will be recorded in the <literal>repmgr.events</literal> table.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
If the standby is not running, the command can be executed on another
|
||||||
|
node by providing the id of the node to be unregistered using
|
||||||
|
the command line parameter <literal>--node-id</literal>, e.g. executing the following
|
||||||
|
command on the master server will unregister the standby with
|
||||||
|
id <literal>3</literal>:
|
||||||
|
<programlisting>
|
||||||
|
repmgr standby unregister -f /etc/repmgr.conf --node-id=3
|
||||||
|
</programlisting>
|
||||||
|
</para>
|
||||||
|
</chapter>
|
||||||
|
|
||||||
117
doc/repmgr.sgml
Normal file
117
doc/repmgr.sgml
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
<!-- doc/src/sgml/postgres.sgml -->
|
||||||
|
|
||||||
|
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook V4.2//EN" [
|
||||||
|
|
||||||
|
<!ENTITY % version SYSTEM "version.sgml">
|
||||||
|
%version;
|
||||||
|
|
||||||
|
<!ENTITY % filelist SYSTEM "filelist.sgml">
|
||||||
|
%filelist;
|
||||||
|
|
||||||
|
<!ENTITY repmgr "<productname>repmgr</productname>">
|
||||||
|
<!ENTITY postgres "<productname>PostgreSQL</productname>">
|
||||||
|
]>
|
||||||
|
|
||||||
|
<book id="repmgr">
|
||||||
|
<title>repmgr &repmgrversion; Documentation</title>
|
||||||
|
|
||||||
|
<bookinfo>
|
||||||
|
<corpauthor>2ndQuadrant Ltd</corpauthor>
|
||||||
|
<productname>repmgr</productname>
|
||||||
|
<productnumber>&repmgrversion;</productnumber>
|
||||||
|
&legal;
|
||||||
|
|
||||||
|
<abstract>
|
||||||
|
<para>
|
||||||
|
Thisis the official documentation of &repmgr; &repmgrversion; for
|
||||||
|
use with PostgreSQL 9.3 - PostgreSQL 10.
|
||||||
|
It describes the functionality supported by the current version of &repmgr;.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
repmgr was developed by
|
||||||
|
<ulink url="https://2ndquadrant.com">2ndQuadrant</ulink>
|
||||||
|
along with contributions from other individuals and companies.
|
||||||
|
Contributions from the community are appreciated and welcome - get
|
||||||
|
in touch via <ulink url="https://github.com/2ndQuadrant/repmgr">github</>
|
||||||
|
or <ulink url="https://groups.google.com/group/repmgr">the mailing list/forum</>.
|
||||||
|
Multiple 2ndQuadrant customers contribute funding
|
||||||
|
to make repmgr development possible.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
2ndQuadrant, a Platinum sponsor of the PostgreSQL project,
|
||||||
|
continues to develop repmgr to meet internal needs and those of customers.
|
||||||
|
Other companies as well as individual developers
|
||||||
|
are welcome to participate in the efforts.
|
||||||
|
</para>
|
||||||
|
</abstract>
|
||||||
|
|
||||||
|
<keywordset>
|
||||||
|
<keyword>repmgr</keyword>
|
||||||
|
<keyword>PostgreSQL</keyword>
|
||||||
|
<keyword>replication</keyword>
|
||||||
|
<keyword>asynchronous</keyword>
|
||||||
|
<keyword>HA</keyword>
|
||||||
|
<keyword>high-availability</keyword>
|
||||||
|
</keywordset>
|
||||||
|
</bookinfo>
|
||||||
|
|
||||||
|
|
||||||
|
<part id="getting-started">
|
||||||
|
<title>Getting started</title>
|
||||||
|
&overview;
|
||||||
|
&install;
|
||||||
|
&quickstart;
|
||||||
|
</part>
|
||||||
|
|
||||||
|
<part id="repmgr-administration-manual">
|
||||||
|
<title>repmgr administration manual</title>
|
||||||
|
|
||||||
|
&configuration;
|
||||||
|
&cloning-standbys;
|
||||||
|
&promoting-standby;
|
||||||
|
&follow-new-primary;
|
||||||
|
&switchover;
|
||||||
|
&event-notifications;
|
||||||
|
&upgrading-repmgr;
|
||||||
|
</part>
|
||||||
|
|
||||||
|
<part id="using-repmgrd">
|
||||||
|
<title>Using repmgrd</title>
|
||||||
|
&repmgrd-automatic-failover;
|
||||||
|
&repmgrd-configuration;
|
||||||
|
&repmgrd-demonstration;
|
||||||
|
&repmgrd-cascading-replication;
|
||||||
|
&repmgrd-network-split;
|
||||||
|
&repmgrd-degraded-monitoring;
|
||||||
|
&repmgrd-monitoring;
|
||||||
|
</part>
|
||||||
|
|
||||||
|
<part id="repmgr-command-reference">
|
||||||
|
<title>repmgr command reference</title>
|
||||||
|
|
||||||
|
&repmgr-primary-register;
|
||||||
|
&repmgr-primary-unregister;
|
||||||
|
&repmgr-standby-clone;
|
||||||
|
&repmgr-standby-register;
|
||||||
|
&repmgr-standby-unregister;
|
||||||
|
&repmgr-standby-promote;
|
||||||
|
&repmgr-standby-follow;
|
||||||
|
&repmgr-standby-switchover;
|
||||||
|
&repmgr-node-status;
|
||||||
|
&repmgr-node-check;
|
||||||
|
&repmgr-node-rejoin;
|
||||||
|
&repmgr-cluster-show;
|
||||||
|
&repmgr-cluster-matrix;
|
||||||
|
&repmgr-cluster-crosscheck;
|
||||||
|
&repmgr-cluster-event;
|
||||||
|
&repmgr-cluster-cleanup;
|
||||||
|
</part>
|
||||||
|
|
||||||
|
&appendix-signatures;
|
||||||
|
|
||||||
|
<![%include-index;[&bookindex;]]>
|
||||||
|
<![%include-xslt-index;[<index id="bookindex"></index>]]>
|
||||||
|
|
||||||
|
</book>
|
||||||
12
doc/repmgrd-automatic-failover.sgml
Normal file
12
doc/repmgrd-automatic-failover.sgml
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<chapter id="repmgrd-automatic-failover" xreflabel="Automatic failover with repmgrd">
|
||||||
|
<title>Automatic failover with repmgrd</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
<command>repmgrd</command> is a management and monitoring daemon which runs
|
||||||
|
on each node in a replication cluster. It can automate actions such as
|
||||||
|
failover and updating standbys to follow the new primary, as well as
|
||||||
|
providing monitoring information about the state of each standby.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
|
||||||
|
</chapter>
|
||||||
17
doc/repmgrd-cascading-replication.sgml
Normal file
17
doc/repmgrd-cascading-replication.sgml
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<chapter id="repmgrd-cascading-replication">
|
||||||
|
<title>repmgrd and cascading replication</title>
|
||||||
|
<para>
|
||||||
|
Cascading replication - where a standby can connect to an upstream node and not
|
||||||
|
the primary server itself - was introduced in PostgreSQL 9.2. &repmgr; and
|
||||||
|
<command>repmgrd</command> support cascading replication by keeping track of the relationship
|
||||||
|
between standby servers - each node record is stored with the node id of its
|
||||||
|
upstream ("parent") server (except of course the primary server).
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
In a failover situation where the primary node fails and a top-level standby
|
||||||
|
is promoted, a standby connected to another standby will not be affected
|
||||||
|
and continue working as normal (even if the upstream standby it's connected
|
||||||
|
to becomes the primary node). If however the node's direct upstream fails,
|
||||||
|
the "cascaded standby" will attempt to reconnect to that node's parent.
|
||||||
|
</para>
|
||||||
|
</chapter>
|
||||||
94
doc/repmgrd-configuration.sgml
Normal file
94
doc/repmgrd-configuration.sgml
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
<chapter id="repmgrd-configuration">
|
||||||
|
<title>repmgrd configuration</title>
|
||||||
|
<para>
|
||||||
|
To use <command>repmgrd</command>, its associated function library must be
|
||||||
|
included in <filename>postgresql.conf</filename> with:
|
||||||
|
|
||||||
|
<programlisting>
|
||||||
|
shared_preload_libraries = 'repmgr'</programlisting>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Changing this setting requires a restart of PostgreSQL; for more details see
|
||||||
|
the <ulink url="https://www.postgresql.org/docs/current/static/runtime-config-client.html#GUC-SHARED-PRELOAD-LIBRARIES">PostgreSQL documentation</ulink>.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Additionally the following <command>repmgrd</command> options *must* be set in
|
||||||
|
<filename>repmgr.conf</filename> (adjust configuration file locations as appropriate):
|
||||||
|
<programlisting>
|
||||||
|
failover=automatic
|
||||||
|
promote_command='repmgr standby promote -f /etc/repmgr.conf --log-to-file'
|
||||||
|
follow_command='repmgr standby follow -f /etc/repmgr.conf --log-to-file --upstream-node-id=%n'</programlisting>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Note that the <literal>--log-to-file</literal> option will cause
|
||||||
|
output generated by the &repmgr; command, when executed by <command>repmgrd</command>,
|
||||||
|
to be logged to the same destination configured to receive log output for <command>repmgrd</command>.
|
||||||
|
See <filename>repmgr.conf.sample</filename> for further <command>repmgrd</command>-specific settings.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
When <varname>failover</varname> is set to <literal>automatic</literal>, upon detecting failure
|
||||||
|
of the current primary, <command>repmgrd</command> will execute one of
|
||||||
|
<varname>promote_command</varname> or <varname>follow_command</varname>,
|
||||||
|
depending on whether the current server is to become the new primary, or
|
||||||
|
needs to follow another server which has become the new primary. Note that
|
||||||
|
these commands can be any valid shell script which results in one of these
|
||||||
|
two actions happening, but if &repmgr;'s <command>standby follow</command> or
|
||||||
|
<command>standby promote</command>
|
||||||
|
commands are not executed (either directly as shown here, or from a script which
|
||||||
|
performs other actions), the &repmgr; metadata will not be updated and
|
||||||
|
&repmgr; will no longer function reliably.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The <varname>follow_command</varname> should provide the <literal>--upstream-node-id=%n</literal>
|
||||||
|
option to <command>repmgr standby follow</command>; the <literal>%n</literal> will be replaced by
|
||||||
|
<command>repmgrd</command> with the ID of the new primary node. If this is not provided, &repmgr;
|
||||||
|
will attempt to determine the new primary by itself, but if the
|
||||||
|
original primary comes back online after the new primary is promoted, there is a risk that
|
||||||
|
<command>repmgr standby follow</command> will result in the node continuing to follow
|
||||||
|
the original primary.
|
||||||
|
</para>
|
||||||
|
<sect1 id="repmgrd-connection-settings">
|
||||||
|
<title>repmgrd connection settings</title>
|
||||||
|
<para>
|
||||||
|
In addition to the &repmgr; configuration settings, parameters in the
|
||||||
|
<varname>conninfo</varname> string influence how &repmgr; makes a network connection to
|
||||||
|
PostgreSQL. In particular, if another server in the replication cluster
|
||||||
|
is unreachable at network level, system network settings will influence
|
||||||
|
the length of time it takes to determine that the connection is not possible.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
In particular explicitly setting a parameter for <literal>connect_timeout</literal>
|
||||||
|
should be considered; the effective minimum value of <literal>2</literal>
|
||||||
|
(seconds) will ensure that a connection failure at network level is reported
|
||||||
|
as soon as possible, otherwise depending on the system settings (e.g.
|
||||||
|
<varname>tcp_syn_retries</varname> in Linux) a delay of a minute or more
|
||||||
|
is possible.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
For further details on <varname>conninfo</varname> network connection
|
||||||
|
parameters, see the
|
||||||
|
<ulink url="https://www.postgresql.org/docs/current/static/libpq-connect.html#LIBPQ-PARAMKEYWORDS">PostgreSQL documentation</ulink>.
|
||||||
|
</para>
|
||||||
|
</sect1>
|
||||||
|
<sect1 id="repmgrd-log-rotation">
|
||||||
|
<title>repmgrd log rotation</title>
|
||||||
|
<para>
|
||||||
|
To ensure the current <command>repmgrd</command> logfile does not grow
|
||||||
|
indefinitely, configure your system's <command>logrotate</command> to
|
||||||
|
regularly rotate it.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Sample configuration to rotate logfiles weekly with retention for
|
||||||
|
up to 52 weeks and rotation forced if a file grows beyond 100Mb:
|
||||||
|
<programlisting>
|
||||||
|
/var/log/postgresql/repmgr-9.6.log {
|
||||||
|
missingok
|
||||||
|
compress
|
||||||
|
rotate 52
|
||||||
|
maxsize 100M
|
||||||
|
weekly
|
||||||
|
create 0600 postgres postgres
|
||||||
|
}</programlisting>
|
||||||
|
</para>
|
||||||
|
</sect1>
|
||||||
|
</chapter>
|
||||||
70
doc/repmgrd-degraded-monitoring.sgml
Normal file
70
doc/repmgrd-degraded-monitoring.sgml
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
<chapter id="repmgrd-degraded-monitoring">
|
||||||
|
<title>"degraded monitoring" mode</title>
|
||||||
|
<para>
|
||||||
|
In certain circumstances, <command>repmgrd</command> is not able to fulfill its primary mission
|
||||||
|
of monitoring the nodes' upstream server. In these cases it enters "degraded
|
||||||
|
monitoring" mode, where <command>repmgrd</command> remains active but is waiting for the situation
|
||||||
|
to be resolved.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Situations where this happens are:
|
||||||
|
<itemizedlist spacing="compact" mark="bullet">
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>a failover situation has occurred, no nodes in the primary node's location are visible</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>a failover situation has occurred, but no promotion candidate is available</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>a failover situation has occurred, but the promotion candidate could not be promoted</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>a failover situation has occurred, but the node was unable to follow the new primary</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>a failover situation has occurred, but no primary has become available</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>a failover situation has occurred, but automatic failover is not enabled for the node</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>repmgrd is monitoring the primary node, but it is not available</simpara>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Example output in a situation where there is only one standby with <literal>failover=manual</literal>,
|
||||||
|
and the primary node is unavailable (but is later restarted):
|
||||||
|
<programlisting>
|
||||||
|
[2017-08-29 10:59:19] [INFO] node "node2" (node ID: 2) monitoring upstream node "node1" (node ID: 1) in normal state (automatic failover disabled)
|
||||||
|
[2017-08-29 10:59:33] [WARNING] unable to connect to upstream node "node1" (node ID: 1)
|
||||||
|
[2017-08-29 10:59:33] [INFO] checking state of node 1, 1 of 5 attempts
|
||||||
|
[2017-08-29 10:59:33] [INFO] sleeping 1 seconds until next reconnection attempt
|
||||||
|
(...)
|
||||||
|
[2017-08-29 10:59:37] [INFO] checking state of node 1, 5 of 5 attempts
|
||||||
|
[2017-08-29 10:59:37] [WARNING] unable to reconnect to node 1 after 5 attempts
|
||||||
|
[2017-08-29 10:59:37] [NOTICE] this node is not configured for automatic failover so will not be considered as promotion candidate
|
||||||
|
[2017-08-29 10:59:37] [NOTICE] no other nodes are available as promotion candidate
|
||||||
|
[2017-08-29 10:59:37] [HINT] use "repmgr standby promote" to manually promote this node
|
||||||
|
[2017-08-29 10:59:37] [INFO] node "node2" (node ID: 2) monitoring upstream node "node1" (node ID: 1) in degraded state (automatic failover disabled)
|
||||||
|
[2017-08-29 10:59:53] [INFO] node "node2" (node ID: 2) monitoring upstream node "node1" (node ID: 1) in degraded state (automatic failover disabled)
|
||||||
|
[2017-08-29 11:00:45] [NOTICE] reconnected to upstream node 1 after 68 seconds, resuming monitoring
|
||||||
|
[2017-08-29 11:00:57] [INFO] node "node2" (node ID: 2) monitoring upstream node "node1" (node ID: 1) in normal state (automatic failover disabled)</programlisting>
|
||||||
|
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
By default, <literal>repmgrd</literal> will continue in degraded monitoring mode indefinitely.
|
||||||
|
However a timeout (in seconds) can be set with <varname>degraded_monitoring_timeout</varname>,
|
||||||
|
after which <command>repmgrd</command> will terminate.
|
||||||
|
|
||||||
|
</para>
|
||||||
|
|
||||||
|
</chapter>
|
||||||
96
doc/repmgrd-demonstration.sgml
Normal file
96
doc/repmgrd-demonstration.sgml
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
<chapter id="repmgrd-demonstration">
|
||||||
|
<title>repmgrd demonstration</title>
|
||||||
|
<para>
|
||||||
|
To demonstrate automatic failover, set up a 3-node replication cluster (one primary
|
||||||
|
and two standbys streaming directly from the primary) so that the cluster looks
|
||||||
|
something like this:
|
||||||
|
<programlisting>
|
||||||
|
$ repmgr -f /etc/repmgr.conf cluster show
|
||||||
|
ID | Name | Role | Status | Upstream | Location | Connection string
|
||||||
|
----+-------+---------+-----------+----------+----------+--------------------------------------
|
||||||
|
1 | node1 | primary | * running | | default | host=node1 dbname=repmgr user=repmgr
|
||||||
|
2 | node2 | standby | running | node1 | default | host=node2 dbname=repmgr user=repmgr
|
||||||
|
3 | node3 | standby | running | node1 | default | host=node3 dbname=repmgr user=repmgr </programlisting>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Start <command>repmgrd</command> on each standby and verify that it's running by examining the
|
||||||
|
log output, which at log level <literal>INFO</literal> will look like this:
|
||||||
|
<programlisting>
|
||||||
|
[2017-08-24 17:31:00] [NOTICE] using configuration file "/etc/repmgr.conf"
|
||||||
|
[2017-08-24 17:31:00] [INFO] connecting to database "host=node2 dbname=repmgr user=repmgr"
|
||||||
|
[2017-08-24 17:31:00] [NOTICE] starting monitoring of node <literal>node2</literal> (ID: 2)
|
||||||
|
[2017-08-24 17:31:00] [INFO] monitoring connection to upstream node "node1" (node ID: 1) </programlisting>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Each <command>repmgrd</command> should also have recorded its successful startup as an event:
|
||||||
|
<programlisting>
|
||||||
|
$ repmgr -f /etc/repmgr.conf cluster event --event=repmgrd_start
|
||||||
|
Node ID | Name | Event | OK | Timestamp | Details
|
||||||
|
---------+-------+---------------+----+---------------------+-------------------------------------------------------------
|
||||||
|
3 | node3 | repmgrd_start | t | 2017-08-24 17:35:54 | monitoring connection to upstream node "node1" (node ID: 1)
|
||||||
|
2 | node2 | repmgrd_start | t | 2017-08-24 17:35:50 | monitoring connection to upstream node "node1" (node ID: 1)
|
||||||
|
1 | node1 | repmgrd_start | t | 2017-08-24 17:35:46 | monitoring cluster primary "node1" (node ID: 1) </programlisting>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Now stop the current primary server with e.g.:
|
||||||
|
<programlisting>
|
||||||
|
pg_ctl -D /var/lib/postgresql/data -m immediate stop</programlisting>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
This will force the primary to shut down straight away, aborting all processes
|
||||||
|
and transactions. This will cause a flurry of activity in the <command>repmgrd</command> log
|
||||||
|
files as each <command>repmgrd</command> detects the failure of the primary and a failover
|
||||||
|
decision is made. This is an extract from the log of a standby server (<literal>node2</literal>)
|
||||||
|
which has promoted to new primary after failure of the original primary (<literal>node1</literal>).
|
||||||
|
<programlisting>
|
||||||
|
[2017-08-24 23:32:01] [INFO] node "node2" (node ID: 2) monitoring upstream node "node1" (node ID: 1) in normal state
|
||||||
|
[2017-08-24 23:32:08] [WARNING] unable to connect to upstream node "node1" (node ID: 1)
|
||||||
|
[2017-08-24 23:32:08] [INFO] checking state of node 1, 1 of 5 attempts
|
||||||
|
[2017-08-24 23:32:08] [INFO] sleeping 1 seconds until next reconnection attempt
|
||||||
|
[2017-08-24 23:32:09] [INFO] checking state of node 1, 2 of 5 attempts
|
||||||
|
[2017-08-24 23:32:09] [INFO] sleeping 1 seconds until next reconnection attempt
|
||||||
|
[2017-08-24 23:32:10] [INFO] checking state of node 1, 3 of 5 attempts
|
||||||
|
[2017-08-24 23:32:10] [INFO] sleeping 1 seconds until next reconnection attempt
|
||||||
|
[2017-08-24 23:32:11] [INFO] checking state of node 1, 4 of 5 attempts
|
||||||
|
[2017-08-24 23:32:11] [INFO] sleeping 1 seconds until next reconnection attempt
|
||||||
|
[2017-08-24 23:32:12] [INFO] checking state of node 1, 5 of 5 attempts
|
||||||
|
[2017-08-24 23:32:12] [WARNING] unable to reconnect to node 1 after 5 attempts
|
||||||
|
INFO: setting voting term to 1
|
||||||
|
INFO: node 2 is candidate
|
||||||
|
INFO: node 3 has received request from node 2 for electoral term 1 (our term: 0)
|
||||||
|
[2017-08-24 23:32:12] [NOTICE] this node is the winner, will now promote self and inform other nodes
|
||||||
|
INFO: connecting to standby database
|
||||||
|
NOTICE: promoting standby
|
||||||
|
DETAIL: promoting server using '/home/barwick/devel/builds/HEAD/bin/pg_ctl -l /tmp/postgres.5602.log -w -D '/tmp/repmgr-test/node_2/data' promote'
|
||||||
|
INFO: reconnecting to promoted server
|
||||||
|
NOTICE: STANDBY PROMOTE successful
|
||||||
|
DETAIL: node 2 was successfully promoted to primary
|
||||||
|
INFO: node 3 received notification to follow node 2
|
||||||
|
[2017-08-24 23:32:13] [INFO] switching to primary monitoring mode</programlisting>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The cluster status will now look like this, with the original primary (<literal>node1</literal>)
|
||||||
|
marked as inactive, and standby <literal>node3</literal> now following the new primary
|
||||||
|
(<literal>node2</literal>):
|
||||||
|
<programlisting>
|
||||||
|
$ repmgr -f /etc/repmgr.conf cluster show
|
||||||
|
ID | Name | Role | Status | Upstream | Location | Connection string
|
||||||
|
----+-------+---------+-----------+----------+----------+----------------------------------------------------
|
||||||
|
1 | node1 | primary | - failed | | default | host=node1 dbname=repmgr user=repmgr
|
||||||
|
2 | node2 | primary | * running | | default | host=node2 dbname=repmgr user=repmgr
|
||||||
|
3 | node3 | standby | running | node2 | default | host=node3 dbname=repmgr user=repmgr</programlisting>
|
||||||
|
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
<command>repmgr cluster event</command> will display a summary of what happened to each server
|
||||||
|
during the failover:
|
||||||
|
<programlisting>
|
||||||
|
$ repmgr -f /etc/repmgr.conf cluster event
|
||||||
|
Node ID | Name | Event | OK | Timestamp | Details
|
||||||
|
---------+-------+--------------------------+----+---------------------+-----------------------------------------------------------------------------------
|
||||||
|
3 | node3 | repmgrd_failover_follow | t | 2017-08-24 23:32:16 | node 3 now following new upstream node 2
|
||||||
|
3 | node3 | standby_follow | t | 2017-08-24 23:32:16 | node 3 is now attached to node 2
|
||||||
|
2 | node2 | repmgrd_failover_promote | t | 2017-08-24 23:32:13 | node 2 promoted to primary; old primary 1 marked as failed
|
||||||
|
2 | node2 | standby_promote | t | 2017-08-24 23:32:13 | node 2 was successfully promoted to primary</programlisting>
|
||||||
|
</para>
|
||||||
|
</chapter>
|
||||||
71
doc/repmgrd-monitoring.sgml
Normal file
71
doc/repmgrd-monitoring.sgml
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
<chapter id="repmgrd-monitoring">
|
||||||
|
<title>Monitoring with repmgrd</title>
|
||||||
|
<para>
|
||||||
|
When `repmgrd` is running with the option <literal>monitoring_history=true</literal>,
|
||||||
|
it will constantly write standby node status information to the
|
||||||
|
<varname>monitoring_history</varname> table, providing a near-real time
|
||||||
|
overview of replication status on all nodes
|
||||||
|
in the cluster.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The view <literal>replication_status</literal> shows the most recent state
|
||||||
|
for each node, e.g.:
|
||||||
|
<programlisting>
|
||||||
|
repmgr=# select * from repmgr.replication_status;
|
||||||
|
-[ RECORD 1 ]-------------+------------------------------
|
||||||
|
primary_node_id | 1
|
||||||
|
standby_node_id | 2
|
||||||
|
standby_name | node2
|
||||||
|
node_type | standby
|
||||||
|
active | t
|
||||||
|
last_monitor_time | 2017-08-24 16:28:41.260478+09
|
||||||
|
last_wal_primary_location | 0/6D57A00
|
||||||
|
last_wal_standby_location | 0/5000000
|
||||||
|
replication_lag | 29 MB
|
||||||
|
replication_time_lag | 00:00:11.736163
|
||||||
|
apply_lag | 15 MB
|
||||||
|
communication_time_lag | 00:00:01.365643</programlisting>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The interval in which monitoring history is written is controlled by the
|
||||||
|
configuration parameter <varname>monitor_interval_secs</varname>;
|
||||||
|
default is 2.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
As this can generate a large amount of monitoring data in the table
|
||||||
|
<literal>repmgr.monitoring_history</literal>. it's advisable to regularly
|
||||||
|
purge historical data using the <xref linkend="repmgr-cluster-cleanup">
|
||||||
|
command; use the <literal>-k/--keep-history</literal> option to
|
||||||
|
specify how many day's worth of data should be retained.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
It's possible to use <command>repmgrd</command> to run in monitoring
|
||||||
|
mode only (without automatic failover capability) for some or all
|
||||||
|
nodes by setting <literal>failover=manual</literal> in the node's
|
||||||
|
<filename>repmgr.conf</filename> file. In the event of the node's upstream failing,
|
||||||
|
no failover action will be taken and the node will require manual intervention to
|
||||||
|
be reattached to replication. If this occurs, an
|
||||||
|
<link linkend="event-notifications">event notification</link>
|
||||||
|
<varname>standby_disconnect_manual</varname> will be created.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Note that when a standby node is not streaming directly from its upstream
|
||||||
|
node, e.g. recovering WAL from an archive, <varname>apply_lag</varname> will always appear as
|
||||||
|
<literal>0 bytes</literal>.
|
||||||
|
</para>
|
||||||
|
<tip>
|
||||||
|
<para>
|
||||||
|
If monitoring history is enabled, the contents of the <literal>repmgr.monitoring_history</literal>
|
||||||
|
table will be replicated to attached standbys. This means there will be a small but
|
||||||
|
constant stream of replication activity which may not be desirable. To prevent
|
||||||
|
this, convert the table to an <literal>UNLOGGED</literal> one with:
|
||||||
|
<programlisting>
|
||||||
|
ALTER TABLE repmgr.monitoring_history SET UNLOGGED;</programlisting>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
This will however mean that monitoring history will not be available on
|
||||||
|
another node following a failover, and the view <literal>repmgr.replication_status</literal>
|
||||||
|
will not work on standbys.
|
||||||
|
</para>
|
||||||
|
</tip>
|
||||||
|
</chapter>
|
||||||
43
doc/repmgrd-network-split.sgml
Normal file
43
doc/repmgrd-network-split.sgml
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
<chapter id="repmgrd-network-split">
|
||||||
|
<title>Handling network splits with repmgrd</title>
|
||||||
|
<para>
|
||||||
|
A common pattern for replication cluster setups is to spread servers over
|
||||||
|
more than one datacentre. This can provide benefits such as geographically-
|
||||||
|
distributed read replicas and DR (disaster recovery capability). However
|
||||||
|
this also means there is a risk of disconnection at network level between
|
||||||
|
datacentre locations, which would result in a split-brain scenario if
|
||||||
|
servers in a secondary data centre were no longer able to see the primary
|
||||||
|
in the main data centre and promoted a standby among themselves.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Previous &repmgr; versions used the concept of a "witness server" to
|
||||||
|
artificially create a quorum of servers in a particular location, ensuring
|
||||||
|
that nodes in another location will not elect a new primary if they
|
||||||
|
are unable to see the majority of nodes. However this approach does not
|
||||||
|
scale well, particularly with more complex replication setups, e.g.
|
||||||
|
where the majority of nodes are located outside of the primary datacentre.
|
||||||
|
It also means the <literal>witness</literal> node needs to be managed as an
|
||||||
|
extra PostgreSQL instance outside of the main replication cluster, which
|
||||||
|
adds administrative and programming complexity.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
<literal>repmgr4</literal> introduces the concept of <literal>location</literal>:
|
||||||
|
each node is associated with an arbitrary location string (default is
|
||||||
|
<literal>default</literal>); this is set in <filename>repmgr.conf</filename>, e.g.:
|
||||||
|
<programlisting>
|
||||||
|
node_id=1
|
||||||
|
node_name=node1
|
||||||
|
conninfo='host=node1 user=repmgr dbname=repmgr connect_timeout=2'
|
||||||
|
data_directory='/var/lib/postgresql/data'
|
||||||
|
location='dc1'</programlisting>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
In a failover situation, <command>repmgrd</command> will check if any servers in the
|
||||||
|
same location as the current primary node are visible. If not, <command>repmgrd</command>
|
||||||
|
will assume a network interruption and not promote any node in any
|
||||||
|
other location (it will however enter <xref linkend="repmgrd-degraded-monitoring"> mode until
|
||||||
|
a primary becomes visible).
|
||||||
|
</para>
|
||||||
|
|
||||||
|
</chapter>
|
||||||
|
|
||||||
96
doc/stylesheet.css
Normal file
96
doc/stylesheet.css
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
/* doc/src/sgml/stylesheet.css */
|
||||||
|
|
||||||
|
/* color scheme similar to www.postgresql.org */
|
||||||
|
|
||||||
|
BODY {
|
||||||
|
color: #000000;
|
||||||
|
background: #FFFFFF;
|
||||||
|
font-family: verdana, sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
A:link { color:#0066A2; }
|
||||||
|
A:visited { color:#004E66; }
|
||||||
|
A:active { color:#0066A2; }
|
||||||
|
A:hover { color:#000000; }
|
||||||
|
|
||||||
|
H1 {
|
||||||
|
font-size: 1.4em;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-top: 0em;
|
||||||
|
margin-bottom: 0em;
|
||||||
|
color: #EC5800;
|
||||||
|
}
|
||||||
|
|
||||||
|
H2 {
|
||||||
|
font-size: 1.2em;
|
||||||
|
margin: 1.2em 0em 1.2em 0em;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
H3 {
|
||||||
|
font-size: 1.1em;
|
||||||
|
margin: 1.2em 0em 1.2em 0em;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
H4 {
|
||||||
|
font-size: 0.95em;
|
||||||
|
margin: 1.2em 0em 1.2em 0em;
|
||||||
|
font-weight: normal;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
H5 {
|
||||||
|
font-size: 0.9em;
|
||||||
|
margin: 1.2em 0em 1.2em 0em;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
H6 {
|
||||||
|
font-size: 0.85em;
|
||||||
|
margin: 1.2em 0em 1.2em 0em;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* center some titles */
|
||||||
|
|
||||||
|
.BOOK .TITLE, .BOOK .CORPAUTHOR, .BOOK .COPYRIGHT {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* decoration for formal examples */
|
||||||
|
|
||||||
|
DIV.EXAMPLE {
|
||||||
|
padding-left: 15px;
|
||||||
|
border-style: solid;
|
||||||
|
border-width: 0px;
|
||||||
|
border-left-width: 2px;
|
||||||
|
border-color: black;
|
||||||
|
margin: 0.5ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* less dense spacing of TOC */
|
||||||
|
|
||||||
|
.BOOK .TOC DL DT {
|
||||||
|
padding-top: 1.5ex;
|
||||||
|
padding-bottom: 1.5ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.BOOK .TOC DL DL DT {
|
||||||
|
padding-top: 0ex;
|
||||||
|
padding-bottom: 0ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* miscellaneous */
|
||||||
|
|
||||||
|
PRE.LITERALLAYOUT, .SCREEN, .SYNOPSIS, .PROGRAMLISTING {
|
||||||
|
margin-left: 4ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.COMMENT { color: red; }
|
||||||
|
|
||||||
|
VAR { font-family: monospace; font-style: italic; }
|
||||||
|
/* Konqueror's standard style for ACRONYM is italic. */
|
||||||
|
ACRONYM { font-style: inherit; }
|
||||||
851
doc/stylesheet.dsl
Normal file
851
doc/stylesheet.dsl
Normal file
@@ -0,0 +1,851 @@
|
|||||||
|
<!-- doc/src/sgml/stylesheet.dsl -->
|
||||||
|
<!DOCTYPE style-sheet PUBLIC "-//James Clark//DTD DSSSL Style Sheet//EN" [
|
||||||
|
|
||||||
|
<!-- must turn on one of these with -i on the jade command line -->
|
||||||
|
<!ENTITY % output-html "IGNORE">
|
||||||
|
<!ENTITY % output-print "IGNORE">
|
||||||
|
<!ENTITY % output-text "IGNORE">
|
||||||
|
|
||||||
|
<![ %output-html; [
|
||||||
|
<!ENTITY dbstyle PUBLIC "-//Norman Walsh//DOCUMENT DocBook HTML Stylesheet//EN" CDATA DSSSL>
|
||||||
|
]]>
|
||||||
|
|
||||||
|
<![ %output-print; [
|
||||||
|
<!ENTITY dbstyle PUBLIC "-//Norman Walsh//DOCUMENT DocBook Print Stylesheet//EN" CDATA DSSSL>
|
||||||
|
]]>
|
||||||
|
|
||||||
|
<![ %output-text; [
|
||||||
|
<!ENTITY dbstyle PUBLIC "-//Norman Walsh//DOCUMENT DocBook HTML Stylesheet//EN" CDATA DSSSL>
|
||||||
|
]]>
|
||||||
|
|
||||||
|
]>
|
||||||
|
|
||||||
|
<style-sheet>
|
||||||
|
<style-specification use="docbook">
|
||||||
|
<style-specification-body>
|
||||||
|
|
||||||
|
<!-- general customization ......................................... -->
|
||||||
|
|
||||||
|
<!-- (applicable to all output formats) -->
|
||||||
|
|
||||||
|
(define draft-mode #f)
|
||||||
|
|
||||||
|
;; Don't show manpage volume numbers
|
||||||
|
(define %refentry-xref-manvolnum% #f)
|
||||||
|
|
||||||
|
;; Don't use graphics for callouts. (We could probably do that, but
|
||||||
|
;; it needs extra work.)
|
||||||
|
(define %callout-graphics% #f)
|
||||||
|
|
||||||
|
;; Show comments during the development stage.
|
||||||
|
(define %show-comments% draft-mode)
|
||||||
|
|
||||||
|
;; Force a chapter TOC even if it includes only a single entry
|
||||||
|
(define %force-chapter-toc% #t)
|
||||||
|
|
||||||
|
;; Don't append period if run-in title ends with any of these
|
||||||
|
;; characters. We had to add the colon here. This is fixed in
|
||||||
|
;; stylesheets version 1.71, so it can be removed sometime.
|
||||||
|
(define %content-title-end-punct%
|
||||||
|
'(#\. #\! #\? #\:))
|
||||||
|
|
||||||
|
;; No automatic punctuation after honorific name parts
|
||||||
|
(define %honorific-punctuation% "")
|
||||||
|
|
||||||
|
;; Change display of some elements
|
||||||
|
(element command ($mono-seq$))
|
||||||
|
(element envar ($mono-seq$))
|
||||||
|
(element lineannotation ($italic-seq$))
|
||||||
|
(element literal ($mono-seq$))
|
||||||
|
(element option ($mono-seq$))
|
||||||
|
(element parameter ($mono-seq$))
|
||||||
|
(element structfield ($mono-seq$))
|
||||||
|
(element structname ($mono-seq$))
|
||||||
|
(element symbol ($mono-seq$))
|
||||||
|
(element token ($mono-seq$))
|
||||||
|
(element type ($mono-seq$))
|
||||||
|
(element varname ($mono-seq$))
|
||||||
|
(element (programlisting emphasis) ($bold-seq$)) ;; to highlight sections of code
|
||||||
|
|
||||||
|
;; Special support for Tcl synopses
|
||||||
|
(element optional
|
||||||
|
(if (equal? (attribute-string (normalize "role")) "tcl")
|
||||||
|
(make sequence
|
||||||
|
(literal "?")
|
||||||
|
($charseq$)
|
||||||
|
(literal "?"))
|
||||||
|
(make sequence
|
||||||
|
(literal %arg-choice-opt-open-str%)
|
||||||
|
($charseq$)
|
||||||
|
(literal %arg-choice-opt-close-str%))))
|
||||||
|
|
||||||
|
;; Avoid excessive cross-reference labels
|
||||||
|
(define (auto-xref-indirect? target ancestor)
|
||||||
|
(cond
|
||||||
|
; ;; Always add indirect references to another book
|
||||||
|
; ((member (gi ancestor) (book-element-list))
|
||||||
|
; #t)
|
||||||
|
;; Add indirect references to the section or component a block
|
||||||
|
;; is in iff chapters aren't autolabelled. (Otherwise "Figure 1-3"
|
||||||
|
;; is sufficient)
|
||||||
|
((and (member (gi target) (block-element-list))
|
||||||
|
(not %chapter-autolabel%))
|
||||||
|
#t)
|
||||||
|
;; Add indirect references to the component a section is in if
|
||||||
|
;; the sections are not autolabelled
|
||||||
|
((and (member (gi target) (section-element-list))
|
||||||
|
(member (gi ancestor) (component-element-list))
|
||||||
|
(not %section-autolabel%))
|
||||||
|
#t)
|
||||||
|
(else #f)))
|
||||||
|
|
||||||
|
|
||||||
|
;; Bibliography things
|
||||||
|
|
||||||
|
;; Use the titles of bibliography entries in cross-references
|
||||||
|
(define biblio-xref-title #t)
|
||||||
|
|
||||||
|
;; Process bibliography entry components in the order shown below, not
|
||||||
|
;; in the order they appear in the document. (I suppose this should
|
||||||
|
;; be made to fit some publishing standard.)
|
||||||
|
(define %biblioentry-in-entry-order% #f)
|
||||||
|
|
||||||
|
(define (biblioentry-inline-elements)
|
||||||
|
(list
|
||||||
|
(normalize "author")
|
||||||
|
(normalize "authorgroup")
|
||||||
|
(normalize "title")
|
||||||
|
(normalize "subtitle")
|
||||||
|
(normalize "volumenum")
|
||||||
|
(normalize "edition")
|
||||||
|
(normalize "othercredit")
|
||||||
|
(normalize "contrib")
|
||||||
|
(normalize "editor")
|
||||||
|
(normalize "publishername")
|
||||||
|
(normalize "confgroup")
|
||||||
|
(normalize "publisher")
|
||||||
|
(normalize "isbn")
|
||||||
|
(normalize "issn")
|
||||||
|
(normalize "pubsnumber")
|
||||||
|
(normalize "date")
|
||||||
|
(normalize "pubdate")
|
||||||
|
(normalize "pagenums")
|
||||||
|
(normalize "bibliomisc")))
|
||||||
|
|
||||||
|
(mode biblioentry-inline-mode
|
||||||
|
|
||||||
|
(element confgroup
|
||||||
|
(make sequence
|
||||||
|
(literal "Proc. ")
|
||||||
|
(next-match)))
|
||||||
|
|
||||||
|
(element isbn
|
||||||
|
(make sequence
|
||||||
|
(literal "ISBN ")
|
||||||
|
(process-children)))
|
||||||
|
|
||||||
|
(element issn
|
||||||
|
(make sequence
|
||||||
|
(literal "ISSN ")
|
||||||
|
(process-children))))
|
||||||
|
|
||||||
|
|
||||||
|
;; The rules in the default stylesheet for productname format it as a
|
||||||
|
;; paragraph. This may be suitable for productname directly within
|
||||||
|
;; *info, but it's nonsense when productname is used inline, as we do.
|
||||||
|
(mode book-titlepage-recto-mode
|
||||||
|
(element (para productname) ($charseq$)))
|
||||||
|
(mode book-titlepage-verso-mode
|
||||||
|
(element (para productname) ($charseq$)))
|
||||||
|
;; Add more here if needed...
|
||||||
|
|
||||||
|
|
||||||
|
;; Replace a sequence of whitespace in a string by a single space
|
||||||
|
(define (normalize-whitespace str #!optional (whitespace '(#\space #\U-000D)))
|
||||||
|
(let loop ((characters (string->list str))
|
||||||
|
(result '())
|
||||||
|
(prev-was-space #f))
|
||||||
|
(if (null? characters)
|
||||||
|
(list->string (reverse result))
|
||||||
|
(let ((c (car characters))
|
||||||
|
(rest (cdr characters)))
|
||||||
|
(if (member c whitespace)
|
||||||
|
(if prev-was-space
|
||||||
|
(loop rest result #t)
|
||||||
|
(loop rest (cons #\space result) #t))
|
||||||
|
(loop rest (cons c result) #f))))))
|
||||||
|
|
||||||
|
|
||||||
|
<!-- HTML output customization ..................................... -->
|
||||||
|
|
||||||
|
<![ %output-html; [
|
||||||
|
|
||||||
|
(define %section-autolabel% #t)
|
||||||
|
(define %label-preface-sections% #f)
|
||||||
|
(define %generate-legalnotice-link% #t)
|
||||||
|
(define %html-ext% ".html")
|
||||||
|
(define %root-filename% "index")
|
||||||
|
(define %link-mailto-url% (string-append "mailto: repmgr-list@2ndquadrant.com"))
|
||||||
|
(define %use-id-as-filename% #t)
|
||||||
|
(define website-build #f)
|
||||||
|
(define %stylesheet% (if website-build "/resources/docs.css" "website-docs.css"))
|
||||||
|
(define %graphic-default-extension% "gif")
|
||||||
|
(define %body-attr% '())
|
||||||
|
(define ($generate-book-lot-list$) '())
|
||||||
|
(define use-output-dir #t)
|
||||||
|
(define %output-dir% "html")
|
||||||
|
(define html-index-filename "../HTML.index")
|
||||||
|
|
||||||
|
|
||||||
|
;; Only build HTML.index or the actual HTML output, not both. Saves a
|
||||||
|
;; *lot* of time. (overrides docbook.dsl)
|
||||||
|
(root
|
||||||
|
(if (not html-index)
|
||||||
|
(make sequence
|
||||||
|
(process-children)
|
||||||
|
(with-mode manifest
|
||||||
|
(process-children)))
|
||||||
|
(with-mode htmlindex
|
||||||
|
(process-children))))
|
||||||
|
|
||||||
|
|
||||||
|
;; Do not combine first section into chapter chunk.
|
||||||
|
(define (chunk-skip-first-element-list) '())
|
||||||
|
|
||||||
|
;; Returns the depth of auto TOC that should be made at the nd-level
|
||||||
|
(define (toc-depth nd)
|
||||||
|
(cond ((string=? (gi nd) (normalize "book")) 2)
|
||||||
|
((string=? (gi nd) (normalize "part")) 2)
|
||||||
|
((string=? (gi nd) (normalize "chapter")) 2)
|
||||||
|
(else 1)))
|
||||||
|
|
||||||
|
;; Add character encoding and time of creation into HTML header
|
||||||
|
(define %html-header-tags%
|
||||||
|
(list (list "META" '("HTTP-EQUIV" "Content-Type") '("CONTENT" "text/html; charset=ISO-8859-1"))
|
||||||
|
(list "META" '("NAME" "creation") (list "CONTENT" (time->string (time) #t)))))
|
||||||
|
|
||||||
|
|
||||||
|
;; Block elements are allowed in PARA in DocBook, but not in P in
|
||||||
|
;; HTML. With %fix-para-wrappers% turned on, the stylesheets attempt
|
||||||
|
;; to avoid putting block elements in HTML P tags by outputting
|
||||||
|
;; additional end/begin P pairs around them.
|
||||||
|
(define %fix-para-wrappers% #t)
|
||||||
|
|
||||||
|
;; ...but we need to do some extra work to make the above apply to PRE
|
||||||
|
;; as well. (mostly pasted from dbverb.dsl)
|
||||||
|
(define ($verbatim-display$ indent line-numbers?)
|
||||||
|
(let ((content (make element gi: "PRE"
|
||||||
|
attributes: (list
|
||||||
|
(list "CLASS" (gi)))
|
||||||
|
(if (or indent line-numbers?)
|
||||||
|
($verbatim-line-by-line$ indent line-numbers?)
|
||||||
|
(process-children)))))
|
||||||
|
(if %shade-verbatim%
|
||||||
|
(make element gi: "TABLE"
|
||||||
|
attributes: ($shade-verbatim-attr$)
|
||||||
|
(make element gi: "TR"
|
||||||
|
(make element gi: "TD"
|
||||||
|
content)))
|
||||||
|
(make sequence
|
||||||
|
(para-check)
|
||||||
|
content
|
||||||
|
(para-check 'restart)))))
|
||||||
|
|
||||||
|
;; ...and for notes.
|
||||||
|
(element note
|
||||||
|
(make sequence
|
||||||
|
(para-check)
|
||||||
|
($admonition$)
|
||||||
|
(para-check 'restart)))
|
||||||
|
|
||||||
|
;;; XXX The above is very ugly. It might be better to run 'tidy' on
|
||||||
|
;;; the resulting *.html files.
|
||||||
|
|
||||||
|
|
||||||
|
;; Format multiple terms in varlistentry vertically, instead
|
||||||
|
;; of comma-separated.
|
||||||
|
(element (varlistentry term)
|
||||||
|
(make sequence
|
||||||
|
(process-children-trim)
|
||||||
|
(if (not (last-sibling?))
|
||||||
|
(make empty-element gi: "BR")
|
||||||
|
(empty-sosofo))))
|
||||||
|
|
||||||
|
|
||||||
|
;; Customization of header
|
||||||
|
;; - make title a link to the home page
|
||||||
|
;; - add tool tips to Prev/Next links
|
||||||
|
;; - add Up link
|
||||||
|
;; (overrides dbnavig.dsl)
|
||||||
|
(define (default-header-nav-tbl-noff elemnode prev next prevsib nextsib)
|
||||||
|
(let* ((r1? (nav-banner? elemnode))
|
||||||
|
(r1-sosofo (make element gi: "TR"
|
||||||
|
(make element gi: "TH"
|
||||||
|
attributes: (list
|
||||||
|
(list "COLSPAN" "4")
|
||||||
|
(list "ALIGN" "center")
|
||||||
|
(list "VALIGN" "bottom"))
|
||||||
|
(make element gi: "A"
|
||||||
|
attributes: (list
|
||||||
|
(list "HREF" (href-to (nav-home elemnode))))
|
||||||
|
(nav-banner elemnode)))))
|
||||||
|
(r2? (or (not (node-list-empty? prev))
|
||||||
|
(not (node-list-empty? next))
|
||||||
|
(nav-context? elemnode)))
|
||||||
|
(r2-sosofo (make element gi: "TR"
|
||||||
|
(make element gi: "TD"
|
||||||
|
attributes: (list
|
||||||
|
(list "WIDTH" "10%")
|
||||||
|
(list "ALIGN" "left")
|
||||||
|
(list "VALIGN" "top"))
|
||||||
|
(if (node-list-empty? prev)
|
||||||
|
(make entity-ref name: "nbsp")
|
||||||
|
(make element gi: "A"
|
||||||
|
attributes: (list
|
||||||
|
(list "TITLE" (element-title-string prev))
|
||||||
|
(list "HREF"
|
||||||
|
(href-to
|
||||||
|
prev))
|
||||||
|
(list "ACCESSKEY"
|
||||||
|
"P"))
|
||||||
|
(gentext-nav-prev prev))))
|
||||||
|
(make element gi: "TD"
|
||||||
|
attributes: (list
|
||||||
|
(list "WIDTH" "10%")
|
||||||
|
(list "ALIGN" "left")
|
||||||
|
(list "VALIGN" "top"))
|
||||||
|
(if (nav-up? elemnode)
|
||||||
|
(nav-up elemnode)
|
||||||
|
(nav-home-link elemnode)))
|
||||||
|
(make element gi: "TD"
|
||||||
|
attributes: (list
|
||||||
|
(list "WIDTH" "60%")
|
||||||
|
(list "ALIGN" "center")
|
||||||
|
(list "VALIGN" "bottom"))
|
||||||
|
(nav-context elemnode))
|
||||||
|
(make element gi: "TD"
|
||||||
|
attributes: (list
|
||||||
|
(list "WIDTH" "20%")
|
||||||
|
(list "ALIGN" "right")
|
||||||
|
(list "VALIGN" "top"))
|
||||||
|
(if (node-list-empty? next)
|
||||||
|
(make entity-ref name: "nbsp")
|
||||||
|
(make element gi: "A"
|
||||||
|
attributes: (list
|
||||||
|
(list "TITLE" (element-title-string next))
|
||||||
|
(list "HREF"
|
||||||
|
(href-to
|
||||||
|
next))
|
||||||
|
(list "ACCESSKEY"
|
||||||
|
"N"))
|
||||||
|
(gentext-nav-next next)))))))
|
||||||
|
(if (or r1? r2?)
|
||||||
|
(make element gi: "DIV"
|
||||||
|
attributes: '(("CLASS" "NAVHEADER"))
|
||||||
|
(make element gi: "TABLE"
|
||||||
|
attributes: (list
|
||||||
|
(list "SUMMARY" "Header navigation table")
|
||||||
|
(list "WIDTH" %gentext-nav-tblwidth%)
|
||||||
|
(list "BORDER" "0")
|
||||||
|
(list "CELLPADDING" "0")
|
||||||
|
(list "CELLSPACING" "0"))
|
||||||
|
(if r1? r1-sosofo (empty-sosofo))
|
||||||
|
(if r2? r2-sosofo (empty-sosofo)))
|
||||||
|
(make empty-element gi: "HR"
|
||||||
|
attributes: (list
|
||||||
|
(list "ALIGN" "LEFT")
|
||||||
|
(list "WIDTH" %gentext-nav-tblwidth%))))
|
||||||
|
(empty-sosofo))))
|
||||||
|
|
||||||
|
|
||||||
|
;; Put index "quicklinks" (A | B | C | ...) at the top of the bookindex page.
|
||||||
|
|
||||||
|
(element index
|
||||||
|
(let ((preamble (node-list-filter-by-not-gi
|
||||||
|
(children (current-node))
|
||||||
|
(list (normalize "indexentry"))))
|
||||||
|
(indexdivs (node-list-filter-by-gi
|
||||||
|
(children (current-node))
|
||||||
|
(list (normalize "indexdiv"))))
|
||||||
|
(entries (node-list-filter-by-gi
|
||||||
|
(children (current-node))
|
||||||
|
(list (normalize "indexentry")))))
|
||||||
|
(html-document
|
||||||
|
(with-mode head-title-mode
|
||||||
|
(literal (element-title-string (current-node))))
|
||||||
|
(make element gi: "DIV"
|
||||||
|
attributes: (list (list "CLASS" (gi)))
|
||||||
|
($component-separator$)
|
||||||
|
($component-title$)
|
||||||
|
(if (node-list-empty? indexdivs)
|
||||||
|
(empty-sosofo)
|
||||||
|
(make element gi: "P"
|
||||||
|
attributes: (list (list "CLASS" "INDEXDIV-QUICKLINKS"))
|
||||||
|
(with-mode indexdiv-quicklinks-mode
|
||||||
|
(process-node-list indexdivs))))
|
||||||
|
(process-node-list preamble)
|
||||||
|
(if (node-list-empty? entries)
|
||||||
|
(empty-sosofo)
|
||||||
|
(make element gi: "DL"
|
||||||
|
(process-node-list entries)))))))
|
||||||
|
|
||||||
|
|
||||||
|
(mode indexdiv-quicklinks-mode
|
||||||
|
(element indexdiv
|
||||||
|
(make sequence
|
||||||
|
(make element gi: "A"
|
||||||
|
attributes: (list (list "HREF" (href-to (current-node))))
|
||||||
|
(element-title-sosofo))
|
||||||
|
(if (not (last-sibling?))
|
||||||
|
(literal " | ")
|
||||||
|
(literal "")))))
|
||||||
|
|
||||||
|
|
||||||
|
;; Changed to strip and normalize index term content (overrides
|
||||||
|
;; dbindex.dsl)
|
||||||
|
(define (htmlindexterm)
|
||||||
|
(let* ((attr (gi (current-node)))
|
||||||
|
(content (data (current-node)))
|
||||||
|
(string (strip (normalize-whitespace content))) ;; changed
|
||||||
|
(sortas (attribute-string (normalize "sortas"))))
|
||||||
|
(make sequence
|
||||||
|
(make formatting-instruction data: attr)
|
||||||
|
(if sortas
|
||||||
|
(make sequence
|
||||||
|
(make formatting-instruction data: "[")
|
||||||
|
(make formatting-instruction data: sortas)
|
||||||
|
(make formatting-instruction data: "]"))
|
||||||
|
(empty-sosofo))
|
||||||
|
(make formatting-instruction data: " ")
|
||||||
|
(make formatting-instruction data: string)
|
||||||
|
(htmlnewline))))
|
||||||
|
|
||||||
|
(define ($html-body-start$)
|
||||||
|
(if website-build
|
||||||
|
(make empty-element gi: "!--#include virtual=\"/resources/docs-header.html\"--")
|
||||||
|
(empty-sosofo)))
|
||||||
|
|
||||||
|
(define ($html-body-end$)
|
||||||
|
(if website-build
|
||||||
|
(make empty-element gi: "!--#include virtual=\"/resources/docs-footer.html\"--")
|
||||||
|
(empty-sosofo)))
|
||||||
|
|
||||||
|
]]> <!-- %output-html -->
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Print output customization .................................... -->
|
||||||
|
|
||||||
|
<![ %output-print; [
|
||||||
|
|
||||||
|
(define %section-autolabel% #t)
|
||||||
|
(define %default-quadding% 'justify)
|
||||||
|
|
||||||
|
;; Don't know how well hyphenation works with other backends. Might
|
||||||
|
;; turn this on if desired.
|
||||||
|
(define %hyphenation%
|
||||||
|
(if tex-backend #t #f))
|
||||||
|
|
||||||
|
;; Put footnotes at the bottom of the page (rather than end of
|
||||||
|
;; section), and put the URLs of links into footnotes.
|
||||||
|
;;
|
||||||
|
;; bop-footnotes only works with TeX, otherwise it's ignored. But
|
||||||
|
;; when both of these are #t and TeX is used, you need at least
|
||||||
|
;; stylesheets 1.73 because otherwise you don't get any footnotes at
|
||||||
|
;; all for the links.
|
||||||
|
(define bop-footnotes #t)
|
||||||
|
(define %footnote-ulinks% #t)
|
||||||
|
|
||||||
|
(define %refentry-new-page% #t)
|
||||||
|
(define %refentry-keep% #f)
|
||||||
|
|
||||||
|
;; Disabled because of TeX problems
|
||||||
|
;; (http://archives.postgresql.org/pgsql-docs/2007-12/msg00056.php)
|
||||||
|
(define ($generate-book-lot-list$) '())
|
||||||
|
|
||||||
|
;; Indentation of verbatim environments. (This should really be done
|
||||||
|
;; with start-indent in DSSSL.)
|
||||||
|
;; Use of indentation in this area exposes a bug in openjade,
|
||||||
|
;; http://archives.postgresql.org/pgsql-docs/2006-12/msg00064.php
|
||||||
|
;; (define %indent-programlisting-lines% " ")
|
||||||
|
;; (define %indent-screen-lines% " ")
|
||||||
|
;; (define %indent-synopsis-lines% " ")
|
||||||
|
|
||||||
|
|
||||||
|
;; Default graphic format: Jadetex wants eps, pdfjadetex wants pdf.
|
||||||
|
;; (Note that pdfjadetex will not accept eps, that's why we need to
|
||||||
|
;; create a different .tex file for each.) What works with RTF?
|
||||||
|
|
||||||
|
(define texpdf-output #f) ;; override from command line
|
||||||
|
|
||||||
|
(define %graphic-default-extension%
|
||||||
|
(cond (tex-backend (if texpdf-output "pdf" "eps"))
|
||||||
|
(rtf-backend "gif")
|
||||||
|
(else "XXX")))
|
||||||
|
|
||||||
|
;; Need to add pdf here so that the above works. Default setup
|
||||||
|
;; doesn't know about PDF.
|
||||||
|
(define preferred-mediaobject-extensions
|
||||||
|
(list "eps" "ps" "jpg" "jpeg" "pdf" "png"))
|
||||||
|
|
||||||
|
|
||||||
|
;; Don't show links when citing a bibliography entry. This fouls up
|
||||||
|
;; the footnumber counting. To get the link, one can still look into
|
||||||
|
;; the bibliography itself.
|
||||||
|
(mode xref-title-mode
|
||||||
|
(element ulink
|
||||||
|
(process-children)))
|
||||||
|
|
||||||
|
|
||||||
|
;; Format legalnotice justified and with space between paragraphs.
|
||||||
|
(mode book-titlepage-verso-mode
|
||||||
|
(element (legalnotice para)
|
||||||
|
(make paragraph
|
||||||
|
use: book-titlepage-verso-style ;; alter this if ever it needs to appear elsewhere
|
||||||
|
quadding: %default-quadding%
|
||||||
|
line-spacing: (* 0.8 (inherited-line-spacing))
|
||||||
|
font-size: (* 0.8 (inherited-font-size))
|
||||||
|
space-before: (* 0.8 %para-sep%)
|
||||||
|
space-after: (* 0.8 %para-sep%)
|
||||||
|
first-line-start-indent: (if (is-first-para)
|
||||||
|
(* 0.8 %para-indent-firstpara%)
|
||||||
|
(* 0.8 %para-indent%))
|
||||||
|
(process-children))))
|
||||||
|
|
||||||
|
|
||||||
|
;; Fix spacing problems in variablelists
|
||||||
|
|
||||||
|
(element (varlistentry term)
|
||||||
|
(make paragraph
|
||||||
|
space-before: (if (first-sibling?)
|
||||||
|
%para-sep%
|
||||||
|
0pt)
|
||||||
|
keep-with-next?: #t
|
||||||
|
(process-children)))
|
||||||
|
|
||||||
|
(define %varlistentry-indent% 2em)
|
||||||
|
|
||||||
|
(element (varlistentry listitem)
|
||||||
|
(make sequence
|
||||||
|
start-indent: (+ (inherited-start-indent) %varlistentry-indent%)
|
||||||
|
(process-children)))
|
||||||
|
|
||||||
|
|
||||||
|
;; Whitespace fixes for itemizedlists and orderedlists
|
||||||
|
|
||||||
|
(define (process-listitem-content)
|
||||||
|
(if (absolute-first-sibling?)
|
||||||
|
(make sequence
|
||||||
|
(process-children-trim))
|
||||||
|
(next-match)))
|
||||||
|
|
||||||
|
|
||||||
|
;; Default stylesheets format simplelists as tables. This spells
|
||||||
|
;; trouble for Jade. So we just format them as plain lines.
|
||||||
|
|
||||||
|
(define %simplelist-indent% 1em)
|
||||||
|
|
||||||
|
(define (my-simplelist-vert members)
|
||||||
|
(make display-group
|
||||||
|
space-before: %para-sep%
|
||||||
|
space-after: %para-sep%
|
||||||
|
start-indent: (+ %simplelist-indent% (inherited-start-indent))
|
||||||
|
(process-children)))
|
||||||
|
|
||||||
|
(element simplelist
|
||||||
|
(let ((type (attribute-string (normalize "type")))
|
||||||
|
(cols (if (attribute-string (normalize "columns"))
|
||||||
|
(if (> (string->number (attribute-string (normalize "columns"))) 0)
|
||||||
|
(string->number (attribute-string (normalize "columns")))
|
||||||
|
1)
|
||||||
|
1))
|
||||||
|
(members (select-elements (children (current-node)) (normalize "member"))))
|
||||||
|
(cond
|
||||||
|
((equal? type (normalize "inline"))
|
||||||
|
(if (equal? (gi (parent (current-node)))
|
||||||
|
(normalize "para"))
|
||||||
|
(process-children)
|
||||||
|
(make paragraph
|
||||||
|
space-before: %para-sep%
|
||||||
|
space-after: %para-sep%
|
||||||
|
start-indent: (inherited-start-indent))))
|
||||||
|
((equal? type (normalize "vert"))
|
||||||
|
(my-simplelist-vert members))
|
||||||
|
((equal? type (normalize "horiz"))
|
||||||
|
(simplelist-table 'row cols members)))))
|
||||||
|
|
||||||
|
(element member
|
||||||
|
(let ((type (inherited-attribute-string (normalize "type"))))
|
||||||
|
(cond
|
||||||
|
((equal? type (normalize "inline"))
|
||||||
|
(make sequence
|
||||||
|
(process-children)
|
||||||
|
(if (not (last-sibling?))
|
||||||
|
(literal ", ")
|
||||||
|
(literal ""))))
|
||||||
|
((equal? type (normalize "vert"))
|
||||||
|
(make paragraph
|
||||||
|
space-before: 0pt
|
||||||
|
space-after: 0pt))
|
||||||
|
((equal? type (normalize "horiz"))
|
||||||
|
(make paragraph
|
||||||
|
quadding: 'start
|
||||||
|
(process-children))))))
|
||||||
|
|
||||||
|
|
||||||
|
;; Jadetex doesn't handle links to the content of tables, so
|
||||||
|
;; indexterms that point to table entries will go nowhere. We fix
|
||||||
|
;; this by pointing the index entry to the table itself instead, which
|
||||||
|
;; should be equally useful in practice.
|
||||||
|
|
||||||
|
(define (find-parent-table nd)
|
||||||
|
(let ((table (ancestor-member nd ($table-element-list$))))
|
||||||
|
(if (node-list-empty? table)
|
||||||
|
nd
|
||||||
|
table)))
|
||||||
|
|
||||||
|
;; (The function below overrides the one in print/dbindex.dsl.)
|
||||||
|
|
||||||
|
(define (indexentry-link nd)
|
||||||
|
(let* ((id (attribute-string (normalize "role") nd))
|
||||||
|
(prelim-target (find-indexterm id))
|
||||||
|
(target (find-parent-table prelim-target))
|
||||||
|
(preferred (not (node-list-empty?
|
||||||
|
(select-elements (children (current-node))
|
||||||
|
(normalize "emphasis")))))
|
||||||
|
(sosofo (if (node-list-empty? target)
|
||||||
|
(literal "?")
|
||||||
|
(make link
|
||||||
|
destination: (node-list-address target)
|
||||||
|
(with-mode toc-page-number-mode
|
||||||
|
(process-node-list target))))))
|
||||||
|
(if preferred
|
||||||
|
(make sequence
|
||||||
|
font-weight: 'bold
|
||||||
|
sosofo)
|
||||||
|
sosofo)))
|
||||||
|
|
||||||
|
|
||||||
|
;; By default, the part and reference title pages get wrong page
|
||||||
|
;; numbers: The first title page gets roman numerals carried over from
|
||||||
|
;; preface/toc -- we want Arabic numerals. We also need to make sure
|
||||||
|
;; that page-number-restart is set of #f explicitly, because otherwise
|
||||||
|
;; it will carry over from the previous component, which is not good.
|
||||||
|
;;
|
||||||
|
;; (This looks worse than it is. It's copied from print/dbttlpg.dsl
|
||||||
|
;; and common/dbcommon.dsl and modified in minor detail.)
|
||||||
|
|
||||||
|
(define (first-part?)
|
||||||
|
(let* ((book (ancestor (normalize "book")))
|
||||||
|
(nd (ancestor-member (current-node)
|
||||||
|
(append
|
||||||
|
(component-element-list)
|
||||||
|
(division-element-list))))
|
||||||
|
(bookch (children book)))
|
||||||
|
(let loop ((nl bookch))
|
||||||
|
(if (node-list-empty? nl)
|
||||||
|
#f
|
||||||
|
(if (equal? (gi (node-list-first nl)) (normalize "part"))
|
||||||
|
(if (node-list=? (node-list-first nl) nd)
|
||||||
|
#t
|
||||||
|
#f)
|
||||||
|
(loop (node-list-rest nl)))))))
|
||||||
|
|
||||||
|
(define (first-reference?)
|
||||||
|
(let* ((book (ancestor (normalize "book")))
|
||||||
|
(nd (ancestor-member (current-node)
|
||||||
|
(append
|
||||||
|
(component-element-list)
|
||||||
|
(division-element-list))))
|
||||||
|
(bookch (children book)))
|
||||||
|
(let loop ((nl bookch))
|
||||||
|
(if (node-list-empty? nl)
|
||||||
|
#f
|
||||||
|
(if (equal? (gi (node-list-first nl)) (normalize "reference"))
|
||||||
|
(if (node-list=? (node-list-first nl) nd)
|
||||||
|
#t
|
||||||
|
#f)
|
||||||
|
(loop (node-list-rest nl)))))))
|
||||||
|
|
||||||
|
|
||||||
|
(define (part-titlepage elements #!optional (side 'recto))
|
||||||
|
(let ((nodelist (titlepage-nodelist
|
||||||
|
(if (equal? side 'recto)
|
||||||
|
(reference-titlepage-recto-elements)
|
||||||
|
(reference-titlepage-verso-elements))
|
||||||
|
elements))
|
||||||
|
;; partintro is a special case...
|
||||||
|
(partintro (node-list-first
|
||||||
|
(node-list-filter-by-gi elements (list (normalize "partintro"))))))
|
||||||
|
(if (part-titlepage-content? elements side)
|
||||||
|
(make simple-page-sequence
|
||||||
|
page-n-columns: %titlepage-n-columns%
|
||||||
|
;; Make sure that page number format is correct.
|
||||||
|
page-number-format: ($page-number-format$)
|
||||||
|
;; Make sure that the page number is set to 1 if this is the
|
||||||
|
;; first part in the book
|
||||||
|
page-number-restart?: (first-part?)
|
||||||
|
input-whitespace-treatment: 'collapse
|
||||||
|
use: default-text-style
|
||||||
|
|
||||||
|
;; This hack is required for the RTF backend. If an external-graphic
|
||||||
|
;; is the first thing on the page, RTF doesn't seem to do the right
|
||||||
|
;; thing (the graphic winds up on the baseline of the first line
|
||||||
|
;; of the page, left justified). This "one point rule" fixes
|
||||||
|
;; that problem.
|
||||||
|
(make paragraph
|
||||||
|
line-spacing: 1pt
|
||||||
|
(literal ""))
|
||||||
|
|
||||||
|
(let loop ((nl nodelist) (lastnode (empty-node-list)))
|
||||||
|
(if (node-list-empty? nl)
|
||||||
|
(empty-sosofo)
|
||||||
|
(make sequence
|
||||||
|
(if (or (node-list-empty? lastnode)
|
||||||
|
(not (equal? (gi (node-list-first nl))
|
||||||
|
(gi lastnode))))
|
||||||
|
(part-titlepage-before (node-list-first nl) side)
|
||||||
|
(empty-sosofo))
|
||||||
|
(cond
|
||||||
|
((equal? (gi (node-list-first nl)) (normalize "subtitle"))
|
||||||
|
(part-titlepage-subtitle (node-list-first nl) side))
|
||||||
|
((equal? (gi (node-list-first nl)) (normalize "title"))
|
||||||
|
(part-titlepage-title (node-list-first nl) side))
|
||||||
|
(else
|
||||||
|
(part-titlepage-default (node-list-first nl) side)))
|
||||||
|
(loop (node-list-rest nl) (node-list-first nl)))))
|
||||||
|
|
||||||
|
(if (and %generate-part-toc%
|
||||||
|
%generate-part-toc-on-titlepage%
|
||||||
|
(equal? side 'recto))
|
||||||
|
(make display-group
|
||||||
|
(build-toc (current-node)
|
||||||
|
(toc-depth (current-node))))
|
||||||
|
(empty-sosofo))
|
||||||
|
|
||||||
|
;; PartIntro is a special case
|
||||||
|
(if (and (equal? side 'recto)
|
||||||
|
(not (node-list-empty? partintro))
|
||||||
|
%generate-partintro-on-titlepage%)
|
||||||
|
($process-partintro$ partintro #f)
|
||||||
|
(empty-sosofo)))
|
||||||
|
|
||||||
|
(empty-sosofo))))
|
||||||
|
|
||||||
|
|
||||||
|
(define (reference-titlepage elements #!optional (side 'recto))
|
||||||
|
(let ((nodelist (titlepage-nodelist
|
||||||
|
(if (equal? side 'recto)
|
||||||
|
(reference-titlepage-recto-elements)
|
||||||
|
(reference-titlepage-verso-elements))
|
||||||
|
elements))
|
||||||
|
;; partintro is a special case...
|
||||||
|
(partintro (node-list-first
|
||||||
|
(node-list-filter-by-gi elements (list (normalize "partintro"))))))
|
||||||
|
(if (reference-titlepage-content? elements side)
|
||||||
|
(make simple-page-sequence
|
||||||
|
page-n-columns: %titlepage-n-columns%
|
||||||
|
;; Make sure that page number format is correct.
|
||||||
|
page-number-format: ($page-number-format$)
|
||||||
|
;; Make sure that the page number is set to 1 if this is the
|
||||||
|
;; first part in the book
|
||||||
|
page-number-restart?: (first-reference?)
|
||||||
|
input-whitespace-treatment: 'collapse
|
||||||
|
use: default-text-style
|
||||||
|
|
||||||
|
;; This hack is required for the RTF backend. If an external-graphic
|
||||||
|
;; is the first thing on the page, RTF doesn't seem to do the right
|
||||||
|
;; thing (the graphic winds up on the baseline of the first line
|
||||||
|
;; of the page, left justified). This "one point rule" fixes
|
||||||
|
;; that problem.
|
||||||
|
(make paragraph
|
||||||
|
line-spacing: 1pt
|
||||||
|
(literal ""))
|
||||||
|
|
||||||
|
(let loop ((nl nodelist) (lastnode (empty-node-list)))
|
||||||
|
(if (node-list-empty? nl)
|
||||||
|
(empty-sosofo)
|
||||||
|
(make sequence
|
||||||
|
(if (or (node-list-empty? lastnode)
|
||||||
|
(not (equal? (gi (node-list-first nl))
|
||||||
|
(gi lastnode))))
|
||||||
|
(reference-titlepage-before (node-list-first nl) side)
|
||||||
|
(empty-sosofo))
|
||||||
|
(cond
|
||||||
|
((equal? (gi (node-list-first nl)) (normalize "author"))
|
||||||
|
(reference-titlepage-author (node-list-first nl) side))
|
||||||
|
((equal? (gi (node-list-first nl)) (normalize "authorgroup"))
|
||||||
|
(reference-titlepage-authorgroup (node-list-first nl) side))
|
||||||
|
((equal? (gi (node-list-first nl)) (normalize "corpauthor"))
|
||||||
|
(reference-titlepage-corpauthor (node-list-first nl) side))
|
||||||
|
((equal? (gi (node-list-first nl)) (normalize "editor"))
|
||||||
|
(reference-titlepage-editor (node-list-first nl) side))
|
||||||
|
((equal? (gi (node-list-first nl)) (normalize "subtitle"))
|
||||||
|
(reference-titlepage-subtitle (node-list-first nl) side))
|
||||||
|
((equal? (gi (node-list-first nl)) (normalize "title"))
|
||||||
|
(reference-titlepage-title (node-list-first nl) side))
|
||||||
|
(else
|
||||||
|
(reference-titlepage-default (node-list-first nl) side)))
|
||||||
|
(loop (node-list-rest nl) (node-list-first nl)))))
|
||||||
|
|
||||||
|
(if (and %generate-reference-toc%
|
||||||
|
%generate-reference-toc-on-titlepage%
|
||||||
|
(equal? side 'recto))
|
||||||
|
(make display-group
|
||||||
|
(build-toc (current-node)
|
||||||
|
(toc-depth (current-node))))
|
||||||
|
(empty-sosofo))
|
||||||
|
|
||||||
|
;; PartIntro is a special case
|
||||||
|
(if (and (equal? side 'recto)
|
||||||
|
(not (node-list-empty? partintro))
|
||||||
|
%generate-partintro-on-titlepage%)
|
||||||
|
($process-partintro$ partintro #f)
|
||||||
|
(empty-sosofo)))
|
||||||
|
|
||||||
|
(empty-sosofo))))
|
||||||
|
|
||||||
|
]]> <!-- %output-print -->
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Plain text output customization ............................... -->
|
||||||
|
|
||||||
|
<!--
|
||||||
|
This is used for making the INSTALL file and others. We customize the
|
||||||
|
HTML stylesheets to be suitable for dumping plain text (via Netscape,
|
||||||
|
Lynx, or similar).
|
||||||
|
-->
|
||||||
|
|
||||||
|
<![ %output-text; [
|
||||||
|
|
||||||
|
(define %section-autolabel% #f)
|
||||||
|
(define %chapter-autolabel% #f)
|
||||||
|
(define $generate-chapter-toc$ (lambda () #f))
|
||||||
|
|
||||||
|
;; For text output, produce "ASCII markup" for emphasis and such.
|
||||||
|
|
||||||
|
(define ($asterix-seq$ #!optional (sosofo (process-children)))
|
||||||
|
(make sequence
|
||||||
|
(literal "*")
|
||||||
|
sosofo
|
||||||
|
(literal "*")))
|
||||||
|
|
||||||
|
(define ($dquote-seq$ #!optional (sosofo (process-children)))
|
||||||
|
(make sequence
|
||||||
|
(literal (gentext-start-quote))
|
||||||
|
sosofo
|
||||||
|
(literal (gentext-end-quote))))
|
||||||
|
|
||||||
|
(element (para command) ($dquote-seq$))
|
||||||
|
(element (para emphasis) ($asterix-seq$))
|
||||||
|
(element (para filename) ($dquote-seq$))
|
||||||
|
(element (para option) ($dquote-seq$))
|
||||||
|
(element (para replaceable) ($dquote-seq$))
|
||||||
|
(element (para userinput) ($dquote-seq$))
|
||||||
|
|
||||||
|
]]> <!-- %output-text -->
|
||||||
|
|
||||||
|
</style-specification-body>
|
||||||
|
</style-specification>
|
||||||
|
|
||||||
|
<external-specification id="docbook" document="dbstyle">
|
||||||
|
</style-sheet>
|
||||||
204
doc/switchover.sgml
Normal file
204
doc/switchover.sgml
Normal file
@@ -0,0 +1,204 @@
|
|||||||
|
<chapter id="performing-switchover" xreflabel="Performing a switchover with repmgr">
|
||||||
|
<title>Performing a switchover with repmgr</title>
|
||||||
|
<para>
|
||||||
|
A typical use-case for replication is a combination of primary and standby
|
||||||
|
server, with the standby serving as a backup which can easily be activated
|
||||||
|
in case of a problem with the primary. Such an unplanned failover would
|
||||||
|
normally be handled by promoting the standby, after which an appropriate
|
||||||
|
action must be taken to restore the old primary.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
In some cases however it's desirable to promote the standby in a planned
|
||||||
|
way, e.g. so maintenance can be performed on the primary; this kind of switchover
|
||||||
|
is supported by the <xref linkend="repmgr-standby-switchover"> command.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
<command>repmgr standby switchover</command> differs from other &repmgr;
|
||||||
|
actions in that it lso performs actions on another server (the demotion
|
||||||
|
candidate), which means passwordless SSH access is required to that server
|
||||||
|
from the one where <command>repmgr standby switchover</command> is executed.
|
||||||
|
</para>
|
||||||
|
<note>
|
||||||
|
<simpara>
|
||||||
|
<command>repmgr standby switchover</command> performs a relatively complex
|
||||||
|
series of operations on two servers, and should therefore be performed after
|
||||||
|
careful preparation and with adequate attention. In particular you should
|
||||||
|
be confident that your network environment is stable and reliable.
|
||||||
|
</simpara>
|
||||||
|
<simpara>
|
||||||
|
Additionally you should be sure that the current primary can be shut down
|
||||||
|
quickly and cleanly. In particular, access from applications should be
|
||||||
|
minimalized or preferably blocked completely. Also be aware that if there
|
||||||
|
is a backlog of files waiting to be archived, PostgreSQL will not shut
|
||||||
|
down until archiving completes.
|
||||||
|
</simpara>
|
||||||
|
<simpara>
|
||||||
|
We recommend running <command>repmgr standby switchover</command> at the
|
||||||
|
most verbose logging level (<literal>--log-level=DEBUG --verbose</literal>)
|
||||||
|
and capturing all output to assist troubleshooting any problems.
|
||||||
|
</simpara>
|
||||||
|
<simpara>
|
||||||
|
Please also read carefully the sections <xref linkend="preparing-for-switchover"> and
|
||||||
|
`Caveats` below.
|
||||||
|
</simpara>
|
||||||
|
</note>
|
||||||
|
|
||||||
|
<sect1 id="preparing-for-switchover" xreflabel="Preparing for switchover">
|
||||||
|
<indexterm>
|
||||||
|
<primary>switchover</primary>
|
||||||
|
<secondary>preparation</secondary>
|
||||||
|
</indexterm>
|
||||||
|
<title>Preparing for switchover</title>
|
||||||
|
<para>
|
||||||
|
As mentioned above, success of the switchover operation depends on &repmgr;
|
||||||
|
being able to shut down the current primary server quickly and cleanly.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Double-check which commands will be used to stop/start/restart the current
|
||||||
|
primary; on the primary execute:
|
||||||
|
<programlisting>
|
||||||
|
repmgr -f /etc./repmgr.conf node service --list --action=stop
|
||||||
|
repmgr -f /etc./repmgr.conf node service --list --action=start
|
||||||
|
repmgr -f /etc./repmgr.conf node service --list --action=restart
|
||||||
|
</programlisting>
|
||||||
|
</para>
|
||||||
|
<note>
|
||||||
|
<simpara>
|
||||||
|
On <literal>systemd</literal> systems we strongly recommend using the appropriate
|
||||||
|
<command>systemctl</command> commands (typically run via <command>sudo</command>) to ensure
|
||||||
|
<literal>systemd</literal> informed about the status of the PostgreSQL service.
|
||||||
|
</simpara>
|
||||||
|
</note>
|
||||||
|
<para>
|
||||||
|
Check that access from applications is minimalized or preferably blocked
|
||||||
|
completely, so applications are not unexpectedly interrupted.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Check there is no significant replication lag on standbys attached to the
|
||||||
|
current primary.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
If WAL file archiving is set up, check that there is no backlog of files waiting
|
||||||
|
to be archived, as PostgreSQL will not finally shut down until all these have been
|
||||||
|
archived. If there is a backlog exceeding <varname>archive_ready_warning</varname> WAL files,
|
||||||
|
`repmgr` will emit a warning before attempting to perform a switchover; you can also check
|
||||||
|
manually with <command>repmgr node check --archive-ready</command>.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Ensure that <command>repmgrd</command> is *not* running anywhere to prevent it unintentionally
|
||||||
|
promoting a node.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Finally, consider executing <command>repmgr standby switchover</command> with the
|
||||||
|
<literal>--dry-run</literal> option; this will perform any necessary checks and inform you about
|
||||||
|
success/failure, and stop before the first actual command is run (which would be the shutdown of the
|
||||||
|
current primary). Example output:
|
||||||
|
<programlisting>
|
||||||
|
$ repmgr standby switchover -f /etc/repmgr.conf --siblings-follow --dry-run
|
||||||
|
NOTICE: checking switchover on node "node2" (ID: 2) in --dry-run mode
|
||||||
|
INFO: SSH connection to host "localhost" succeeded
|
||||||
|
INFO: archive mode is "off"
|
||||||
|
INFO: replication lag on this standby is 0 seconds
|
||||||
|
INFO: all sibling nodes are reachable via SSH
|
||||||
|
NOTICE: local node "node2" (ID: 2) will be promoted to primary; current primary "node1" (ID: 1) will be demoted to standby
|
||||||
|
INFO: following shutdown command would be run on node "node1":
|
||||||
|
"pg_ctl -l /var/log/postgresql/startup.log -D '/var/lib/postgresql/data' -m fast -W stop"
|
||||||
|
</programlisting>
|
||||||
|
</para>
|
||||||
|
</sect1>
|
||||||
|
|
||||||
|
<sect1 id="switchover-execution" xreflabel="Executing the switchover command">
|
||||||
|
<indexterm>
|
||||||
|
<primary>switchover</primary>
|
||||||
|
<secondary>execution</secondary>
|
||||||
|
</indexterm>
|
||||||
|
<title>Executing the switchover command</title>
|
||||||
|
<para>
|
||||||
|
To demonstrate switchover, we will assume a replication cluster with a
|
||||||
|
primary (<literal>node1</literal>) and one standby (<literal>node2</literal>);
|
||||||
|
after the switchover <literal>node2</literal> should become the primary with
|
||||||
|
<literal>node1</literal> following it.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The switchover command must be run from the standby which is to be promoted,
|
||||||
|
and in its simplest form looks like this:
|
||||||
|
<programlisting>
|
||||||
|
$ repmgr -f /etc/repmgr.conf standby switchover
|
||||||
|
NOTICE: executing switchover on node "node2" (ID: 2)
|
||||||
|
INFO: searching for primary node
|
||||||
|
INFO: checking if node 1 is primary
|
||||||
|
INFO: current primary node is 1
|
||||||
|
INFO: SSH connection to host "localhost" succeeded
|
||||||
|
INFO: archive mode is "off"
|
||||||
|
INFO: replication lag on this standby is 0 seconds
|
||||||
|
NOTICE: local node "node2" (ID: 2) will be promoted to primary; current primary "node1" (ID: 1) will be demoted to standby
|
||||||
|
NOTICE: stopping current primary node "node1" (ID: 1)
|
||||||
|
NOTICE: issuing CHECKPOINT
|
||||||
|
DETAIL: executing server command "pg_ctl -l /var/log/postgres/startup.log -D '/var/lib/pgsql/data' -m fast -W stop"
|
||||||
|
INFO: checking primary status; 1 of 6 attempts
|
||||||
|
NOTICE: current primary has been cleanly shut down at location 0/3001460
|
||||||
|
NOTICE: promoting standby to primary
|
||||||
|
DETAIL: promoting server "node2" (ID: 2) using "pg_ctl -l /var/log/postgres/startup.log -w -D '/var/lib/pgsql/data' promote"
|
||||||
|
server promoting
|
||||||
|
NOTICE: STANDBY PROMOTE successful
|
||||||
|
DETAIL: server "node2" (ID: 2) was successfully promoted to primary
|
||||||
|
INFO: setting node 1's primary to node 2
|
||||||
|
NOTICE: starting server using "pg_ctl -l /var/log/postgres/startup.log -w -D '/var/lib/pgsql/data' restart"
|
||||||
|
NOTICE: NODE REJOIN successful
|
||||||
|
DETAIL: node 1 is now attached to node 2
|
||||||
|
NOTICE: switchover was successful
|
||||||
|
DETAIL: node "node2" is now primary
|
||||||
|
NOTICE: STANDBY SWITCHOVER is complete
|
||||||
|
</programlisting>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The old primary is now replicating as a standby from the new primary, and the
|
||||||
|
cluster status will now look like this:
|
||||||
|
<programlisting>
|
||||||
|
$ repmgr -f /etc/repmgr.conf cluster show
|
||||||
|
ID | Name | Role | Status | Upstream | Location | Connection string
|
||||||
|
----+-------+---------+-----------+----------+----------+--------------------------------------
|
||||||
|
1 | node1 | standby | running | node2 | default | host=node1 dbname=repmgr user=repmgr
|
||||||
|
2 | node2 | primary | * running | | default | host=node2 dbname=repmgr user=repmgr
|
||||||
|
</programlisting>
|
||||||
|
</para>
|
||||||
|
</sect1>
|
||||||
|
<sect1 id="switchover-caveats" xreflabel="Caveats">
|
||||||
|
<indexterm>
|
||||||
|
<primary>switchover</primary>
|
||||||
|
<secondary>caveats</secondary>
|
||||||
|
</indexterm>
|
||||||
|
<title>Caveats</title>
|
||||||
|
<para>
|
||||||
|
<itemizedlist spacing="compact" mark="bullet">
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
If using PostgreSQL 9.3 or 9.4, you should ensure that the shutdown command
|
||||||
|
is configured to use PostgreSQL's <varname>fast</varname> shutdown mode (the default in 9.5
|
||||||
|
and later). If relying on <command>pg_ctl</command> to perform database server operations,
|
||||||
|
you should include <literal>-m fast</literal> in <varname>pg_ctl_options</varname>
|
||||||
|
in <filename>repmgr.conf</filename>.
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
<command>pg_rewind</command> *requires* that either <varname>wal_log_hints</varname> is enabled, or that
|
||||||
|
data checksums were enabled when the cluster was initialized. See the
|
||||||
|
<ulink url="https://www.postgresql.org/docs/current/static/app-pgrewind.html">pg_rewind documentation</ulink>
|
||||||
|
for details.
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
<command>repmgrd</command> should not be running with setting <varname>failover=automatic</varname>
|
||||||
|
in <filename>repmgr.conf</filename> when a switchover is carried out, otherwise the
|
||||||
|
<command>repmgrd</command> daemon may try and promote a standby by itself.
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
We hope to remove some of these restrictions in future versions of `repmgr`.
|
||||||
|
</para>
|
||||||
|
</sect1>
|
||||||
|
</chapter>
|
||||||
245
doc/upgrading-repmgr.sgml
Normal file
245
doc/upgrading-repmgr.sgml
Normal file
@@ -0,0 +1,245 @@
|
|||||||
|
<chapter id="upgrading-repmgr" xreflabel="Upgrading repmgr">
|
||||||
|
<title>Upgrading repmgr</title>
|
||||||
|
<para>
|
||||||
|
&repmgr; is updated regularly with point releases (e.g. 4.0.1 to 4.0.2)
|
||||||
|
containing bugfixes and other minor improvements. Any substantial new
|
||||||
|
functionality will be included in a feature release (e.g. 4.0.x to 4.1.x).
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
&repmgr; is implemented as a PostgreSQL extension; to upgrade it, first
|
||||||
|
install the updated package (or compile the updated source), then in the
|
||||||
|
database where the &repmgr; extension is installed, execute
|
||||||
|
<command>ALTER EXTENSION repmgr UPDATE</command>.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
If <command>repmgrd</command> is running, it may be necessary to restart
|
||||||
|
the PostgreSQL server if the upgrade contains changes to the shared object
|
||||||
|
file used by <command>repmgrd</command>; check the release notes for details.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<sect1 id="upgrading-from-repmgr-3">
|
||||||
|
<title>Upgrading from repmgr 3</title>
|
||||||
|
<para>
|
||||||
|
The upgrade process consists of two steps:
|
||||||
|
<orderedlist>
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
converting the repmgr.conf configuration files
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
upgrading the repmgr schema
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
</orderedlist>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
A script is provided to assist with converting <filename>repmgr.conf</filename>.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The schema upgrade (which converts the &repmgr; metadata into
|
||||||
|
a packaged PostgreSQL extension) is normally carried out
|
||||||
|
automatically when the &repmgr; extension is created.
|
||||||
|
</para>
|
||||||
|
<sect2 id="converting-repmgr-conf">
|
||||||
|
<title>Converting repmgr.conf configuration files</title>
|
||||||
|
<para>
|
||||||
|
With a completely new repmgr version, we've taken the opportunity
|
||||||
|
to rename some configuration items have had their names changed for
|
||||||
|
clarity and consistency, both between the configuration file and
|
||||||
|
the column names in <structname>repmgr.nodes</structname>
|
||||||
|
(e.g. <varname>node</varname> to <varname>node_id</varname>), and
|
||||||
|
also for consistency with PostgreSQL naming conventions
|
||||||
|
(e.g. <varname>loglevel</varname> to <varname>log_level</varname>).
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Other configuration items have been changed to command line options,
|
||||||
|
and vice-versa, e.g. to avoid hard-coding items such as a a node's
|
||||||
|
upstream ID, which might change over time.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
&repmgr; will issue a warning about deprecated/altered options.
|
||||||
|
</para>
|
||||||
|
<sect3>
|
||||||
|
<title>Changed parameters in "repmgr.conf"</title>
|
||||||
|
<para>
|
||||||
|
Following parameters have been added:
|
||||||
|
<itemizedlist spacing="compact" mark="bullet">
|
||||||
|
<listitem>
|
||||||
|
<simpara><varname>data_directory</varname>: this is mandatory and must
|
||||||
|
contain the path to the node's data directory</simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara><varname>monitoring_history</varname>: this replaces the
|
||||||
|
<command>repmgrd</command> command line option
|
||||||
|
<literal>--monitoring-history</literal></simpara>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Following parameters have been renamed:
|
||||||
|
</para>
|
||||||
|
<table tocentry="1" id="repmgr3-repmgr4-renamed-parameters">
|
||||||
|
<title>Parameters renamed in repmgr4</title>
|
||||||
|
<tgroup cols="2">
|
||||||
|
<thead>
|
||||||
|
<row>
|
||||||
|
<entry>repmgr3</entry>
|
||||||
|
<entry>repmgr4</entry>
|
||||||
|
</row>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<row>
|
||||||
|
<entry><varname>node</varname></entry>
|
||||||
|
<entry><varname>node_id</varname></entry>
|
||||||
|
</row>
|
||||||
|
<row>
|
||||||
|
<entry><varname>loglevel</varname></entry>
|
||||||
|
<entry><varname>log_level</varname></entry>
|
||||||
|
</row>
|
||||||
|
<row>
|
||||||
|
<entry><varname>logfacility</varname></entry>
|
||||||
|
<entry><varname>log_facility</varname></entry>
|
||||||
|
</row>
|
||||||
|
<row>
|
||||||
|
<entry><varname>logfile</varname></entry>
|
||||||
|
<entry><varname>log_file</varname></entry>
|
||||||
|
</row>
|
||||||
|
<row>
|
||||||
|
<entry><varname>master_reponse_timeout</varname></entry>
|
||||||
|
<entry><varname>async_query_timeout</varname></entry>
|
||||||
|
</row>
|
||||||
|
</tbody>
|
||||||
|
</tgroup>
|
||||||
|
</table>
|
||||||
|
<para>
|
||||||
|
Following parameters have been removed:
|
||||||
|
<itemizedlist spacing="compact" mark="bullet">
|
||||||
|
<listitem>
|
||||||
|
<simpara><varname>cluster</varname>: is no longer required and will
|
||||||
|
be ignored.</simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara><varname>upstream_node_id</varname>: is replaced by the
|
||||||
|
command-line parameter <literal>--upstream-node-id</literal></simpara>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
</para>
|
||||||
|
</sect3>
|
||||||
|
<sect3>
|
||||||
|
<title>Conversion script</title>
|
||||||
|
<para>
|
||||||
|
To assist with conversion of <filename>repmgr.conf</filename> files, a Perl script
|
||||||
|
is provided in <filename>contrib/convert-config.pl</filename>.
|
||||||
|
Use like this:
|
||||||
|
<programlisting>
|
||||||
|
$ ./convert-config.pl /etc/repmgr.conf
|
||||||
|
node_id=2
|
||||||
|
node_name=node2
|
||||||
|
conninfo=host=localhost dbname=repmgr user=repmgr connect_timeout=2
|
||||||
|
pg_ctl_options='-l /var/log/postgres/startup.log'
|
||||||
|
rsync_options=--exclude=postgresql.local.conf --archive
|
||||||
|
log_level=INFO
|
||||||
|
pg_basebackup_options=--no-slot
|
||||||
|
data_directory=</programlisting>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The converted file is printed to <literal>STDOUT</literal> and the original file is not
|
||||||
|
changed.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Please note that the parameter <varname>data_directory</varname> <emphasis>must</emphasis>
|
||||||
|
be provided; if not already present, the conversion script will add an empty
|
||||||
|
placeholder parameter.
|
||||||
|
</para>
|
||||||
|
</sect3>
|
||||||
|
</sect2>
|
||||||
|
<sect2>
|
||||||
|
<title>Upgrading the repmgr schema</title>
|
||||||
|
<para>
|
||||||
|
Ensure <command>repmgrd</command> is not running, or any cron jobs which execute the
|
||||||
|
<command>repmgr</command> binary.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Install <literal>repmgr4</literal>; any <literal>repmgr3</literal> packages should be uninstalled
|
||||||
|
(if not automatically uninstalled already).
|
||||||
|
</para>
|
||||||
|
<sect3>
|
||||||
|
<title>Upgrading from repmgr 3.1.1 or earlier</title>
|
||||||
|
<para>
|
||||||
|
If your repmgr version is 3.1.1 or earlier, you will need to update
|
||||||
|
the schema to the latest version in the 3.x series (3.3.2) before
|
||||||
|
converting the installation to repmgr 4.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
To do this, apply the following upgrade scripts as appropriate for
|
||||||
|
your current version:
|
||||||
|
<itemizedlist spacing="compact" mark="bullet">
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
<ulink url="https://raw.githubusercontent.com/2ndQuadrant/repmgr/REL3_3_STABLE/sql/repmgr3.0_repmgr3.1.sql">repmgr3.0_repmgr3.1.sql</ulink></simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara><ulink url="https://raw.githubusercontent.com/2ndQuadrant/repmgr/REL3_3_STABLE/sql/repmgr3.1.1_repmgr3.1.2.sql">repmgr3.1.1_repmgr3.1.2.sql</ulink></simpara>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
For more details see the
|
||||||
|
<ulink url="https://repmgr.org/release-notes-3.3.2.html#upgrading">repmgr 3 upgrade notes</ulink>.
|
||||||
|
</para>
|
||||||
|
</sect3>
|
||||||
|
<sect3>
|
||||||
|
<title>Manually create the repmgr extension</title>
|
||||||
|
<para>
|
||||||
|
In the database used by the existing &repmgr; installation, execute:
|
||||||
|
<programlisting>
|
||||||
|
CREATE EXTENSION repmgr FROM unpackaged;</programlisting>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
This will move and convert all objects from the existing schema
|
||||||
|
into the new, standard <literal>repmgr</literal> schema.
|
||||||
|
</para>
|
||||||
|
<note>
|
||||||
|
<simpara>there must be only one schema matching <literal>repmgr_%</literal> in the
|
||||||
|
database, otherwise this step may not work.</simpara>
|
||||||
|
</note>
|
||||||
|
</sect3>
|
||||||
|
<sect3>
|
||||||
|
<title>Re-register each node</title>
|
||||||
|
<para>
|
||||||
|
This is necessary to update the <literal>repmgr</literal> metadata with some additional items.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
On the primary node, execute e.g.
|
||||||
|
<programlisting>
|
||||||
|
repmgr primary register -f /etc/repmgr.conf --force</programlisting>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
On each standby node, execute e.g.
|
||||||
|
<programlisting>
|
||||||
|
repmgr standby register -f /etc/repmgr.conf --force</programlisting>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Check the data is updated as expected by examining the <structname>repmgr.nodes</structname>
|
||||||
|
table; restart <command>repmgrd</command> if required.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The original <literal>repmgr_$cluster</literal> schema can be dropped at any time.
|
||||||
|
</para>
|
||||||
|
<tip>
|
||||||
|
<simpara>
|
||||||
|
If you don't care about any data from the existing &repmgr; installation,
|
||||||
|
(e.g. the contents of the <structname>events</structname> and <structname>monitoring</structname>
|
||||||
|
tables), the manual <command>CREATE EXTENSION</command> step can be skipped; just re-register
|
||||||
|
each node, starting with the primary node, and the <literal>repmgr</literal> extension will be
|
||||||
|
automatically created.
|
||||||
|
</simpara>
|
||||||
|
</tip>
|
||||||
|
</sect3>
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
</sect1>
|
||||||
|
|
||||||
|
</chapter>
|
||||||
1
doc/version.sgml
Normal file
1
doc/version.sgml
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<!ENTITY repmgrversion "4.0dev">
|
||||||
469
doc/website-docs.css
Normal file
469
doc/website-docs.css
Normal file
@@ -0,0 +1,469 @@
|
|||||||
|
/* PostgreSQL.org Documentation Style */
|
||||||
|
|
||||||
|
/* requires global.css, table.css and text.css to be loaded before this file! */
|
||||||
|
body {
|
||||||
|
font-family: verdana, sans-serif;
|
||||||
|
font-size: 76%;
|
||||||
|
background: url("/resources/background.png") repeat-x scroll left top transparent;
|
||||||
|
padding: 15px 4%;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* monospace font size fix */
|
||||||
|
pre, code, kbd, samp, tt {
|
||||||
|
font-family: monospace,monospace;
|
||||||
|
font-size: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.NAVHEADER table {
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Container Definitions */
|
||||||
|
|
||||||
|
#docContainerWrap {
|
||||||
|
text-align: center; /* Win IE5 */
|
||||||
|
}
|
||||||
|
|
||||||
|
#docContainer {
|
||||||
|
margin: 0 auto;
|
||||||
|
width: 90%;
|
||||||
|
padding-bottom: 2em;
|
||||||
|
display: block;
|
||||||
|
text-align: left; /* Win IE5 */
|
||||||
|
}
|
||||||
|
|
||||||
|
#docHeader {
|
||||||
|
background-image: url("/media/img/docs/bg_hdr.png");
|
||||||
|
height: 83px;
|
||||||
|
margin: 0px;
|
||||||
|
padding: 0px;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
#docHeaderLogo {
|
||||||
|
position: relative;
|
||||||
|
width: 206px;
|
||||||
|
height: 83px;
|
||||||
|
border: 0px;
|
||||||
|
padding: 0px;
|
||||||
|
margin: 0 0 0 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#docHeaderLogo img {
|
||||||
|
border: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#docNavSearchContainer {
|
||||||
|
padding-bottom: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#docNav, #docVersions {
|
||||||
|
position: relative;
|
||||||
|
text-align: left;
|
||||||
|
margin-left: 10px;
|
||||||
|
margin-top: 5px;
|
||||||
|
color: #666;
|
||||||
|
font-size: 0.95em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#docSearch {
|
||||||
|
position: relative;
|
||||||
|
text-align: right;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
#docTextSize {
|
||||||
|
text-align: right;
|
||||||
|
white-space: nowrap;
|
||||||
|
margin-top: 7px;
|
||||||
|
font-size: 0.95em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#docSearch form {
|
||||||
|
position: relative;
|
||||||
|
top: 5px;
|
||||||
|
right: 0;
|
||||||
|
margin: 0; /* need for IE 5.5 OSX */
|
||||||
|
text-align: right; /* need for IE 5.5 OSX */
|
||||||
|
white-space: nowrap; /* for Opera */
|
||||||
|
}
|
||||||
|
|
||||||
|
#docSearch form label {
|
||||||
|
color: #666;
|
||||||
|
font-size: 0.95em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#docSearch form input {
|
||||||
|
font-size: 0.95em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#docSearch form #submit {
|
||||||
|
font-size: 0.95em;
|
||||||
|
background: #7A7A7A;
|
||||||
|
color: #fff;
|
||||||
|
border: 1px solid #7A7A7A;
|
||||||
|
padding: 1px 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#docSearch form #q {
|
||||||
|
width: 170px;
|
||||||
|
font-size: 0.95em;
|
||||||
|
border: 1px solid #7A7A7A;
|
||||||
|
background: #E1E1E1;
|
||||||
|
color: #000000;
|
||||||
|
padding: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.frmDocSearch {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inpDocSearch {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
#docContent {
|
||||||
|
position: relative;
|
||||||
|
margin-left: 10px;
|
||||||
|
margin-right: 10px;
|
||||||
|
margin-top: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#docFooter {
|
||||||
|
position: relative;
|
||||||
|
font-size: 0.9em;
|
||||||
|
color: #666;
|
||||||
|
line-height: 1.3em;
|
||||||
|
margin-left: 10px;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#docComments {
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#docClear {
|
||||||
|
clear: both;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Heading Definitions */
|
||||||
|
|
||||||
|
h1, h2, h3 {
|
||||||
|
font-weight: bold;
|
||||||
|
margin-top: 2ex;
|
||||||
|
color: #444;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 1.4em;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 1.2em !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 1.1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 a:hover,
|
||||||
|
h2 a:hover,
|
||||||
|
h3 a:hover,
|
||||||
|
h4 a:hover {
|
||||||
|
color: #444;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Text Styles */
|
||||||
|
|
||||||
|
div.SECT2 {
|
||||||
|
margin-top: 4ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.SECT3 {
|
||||||
|
margin-top: 3ex;
|
||||||
|
margin-left: 3ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.txtCurrentLocation {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
p, ol, ul, li {
|
||||||
|
line-height: 1.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.txtCommentsWrap {
|
||||||
|
border: 2px solid #F5F5F5;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.txtCommentsContent {
|
||||||
|
background: #F5F5F5;
|
||||||
|
padding: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.txtCommentsPoster {
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.txtCommentsDate {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.txtCommentsComment {
|
||||||
|
padding: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#docContainer pre code,
|
||||||
|
#docContainer pre tt,
|
||||||
|
#docContainer pre pre,
|
||||||
|
#docContainer tt tt,
|
||||||
|
#docContainer tt code,
|
||||||
|
#docContainer tt pre {
|
||||||
|
font-size: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre.LITERALLAYOUT,
|
||||||
|
.SCREEN,
|
||||||
|
.SYNOPSIS,
|
||||||
|
.PROGRAMLISTING,
|
||||||
|
.REFSYNOPSISDIV p,
|
||||||
|
table.CAUTION,
|
||||||
|
table.WARNING,
|
||||||
|
blockquote.NOTE,
|
||||||
|
blockquote.TIP,
|
||||||
|
table.CALSTABLE {
|
||||||
|
-moz-box-shadow: 3px 3px 5px #DFDFDF;
|
||||||
|
-webkit-box-shadow: 3px 3px 5px #DFDFDF;
|
||||||
|
-khtml-box-shadow: 3px 3px 5px #DFDFDF;
|
||||||
|
-o-box-shadow: 3px 3px 5px #DFDFDF;
|
||||||
|
box-shadow: 3px 3px 5px #DFDFDF;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre.LITERALLAYOUT,
|
||||||
|
.SCREEN,
|
||||||
|
.SYNOPSIS,
|
||||||
|
.PROGRAMLISTING,
|
||||||
|
.REFSYNOPSISDIV p,
|
||||||
|
table.CAUTION,
|
||||||
|
table.WARNING,
|
||||||
|
blockquote.NOTE,
|
||||||
|
blockquote.TIP {
|
||||||
|
color: black;
|
||||||
|
border-width: 1px;
|
||||||
|
border-style: solid;
|
||||||
|
padding: 2ex;
|
||||||
|
margin: 2ex 0 2ex 2ex;
|
||||||
|
overflow: auto;
|
||||||
|
-moz-border-radius: 8px;
|
||||||
|
-webkit-border-radius: 8px;
|
||||||
|
-khtml-border-radius: 8px;
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre.LITERALLAYOUT,
|
||||||
|
pre.SYNOPSIS,
|
||||||
|
pre.PROGRAMLISTING,
|
||||||
|
.REFSYNOPSISDIV p,
|
||||||
|
.SCREEN {
|
||||||
|
border-color: #CFCFCF;
|
||||||
|
background-color: #F7F7F7;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote.NOTE,
|
||||||
|
blockquote.TIP {
|
||||||
|
border-color: #DBDBCC;
|
||||||
|
background-color: #EEEEDD;
|
||||||
|
padding: 14px;
|
||||||
|
width: 572px;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote.NOTE,
|
||||||
|
blockquote.TIP,
|
||||||
|
table.CAUTION,
|
||||||
|
table.WARNING {
|
||||||
|
margin: 4ex auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote.NOTE p,
|
||||||
|
blockquote.TIP p {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote.NOTE pre,
|
||||||
|
blockquote.NOTE code,
|
||||||
|
blockquote.TIP pre,
|
||||||
|
blockquote.TIP code {
|
||||||
|
margin-left: 0;
|
||||||
|
margin-right: 0;
|
||||||
|
-moz-box-shadow: none;
|
||||||
|
-webkit-box-shadow: none;
|
||||||
|
-khtml-box-shadow: none;
|
||||||
|
-o-box-shadow: none;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.emphasis,
|
||||||
|
.c2 {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.REPLACEABLE {
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Table Styles */
|
||||||
|
|
||||||
|
table {
|
||||||
|
margin-left: 2ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.CALSTABLE td,
|
||||||
|
table.CALSTABLE th,
|
||||||
|
table.CAUTION td,
|
||||||
|
table.CAUTION th,
|
||||||
|
table.WARNING td,
|
||||||
|
table.WARNING th {
|
||||||
|
border-style: solid;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.CALSTABLE,
|
||||||
|
table.CAUTION,
|
||||||
|
table.WARNING {
|
||||||
|
border-spacing: 0;
|
||||||
|
border-collapse: collapse;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.CALSTABLE
|
||||||
|
{
|
||||||
|
margin: 2ex 0 2ex 2ex;
|
||||||
|
background-color: #E0ECEF;
|
||||||
|
border: 2px solid #A7C6DF;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.CALSTABLE tr:hover td
|
||||||
|
{
|
||||||
|
background-color: #EFEFEF;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.CALSTABLE td {
|
||||||
|
background-color: #FFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.CALSTABLE td,
|
||||||
|
table.CALSTABLE th {
|
||||||
|
border: 1px solid #A7C6DF;
|
||||||
|
padding: 0.5ex 0.5ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.CAUTION,
|
||||||
|
table.WARNING {
|
||||||
|
border-collapse: separate;
|
||||||
|
display: block;
|
||||||
|
padding: 0;
|
||||||
|
max-width: 600px;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.CAUTION {
|
||||||
|
background-color: #F5F5DC;
|
||||||
|
border-color: #DEDFA7;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.WARNING {
|
||||||
|
background-color: #FFD7D7;
|
||||||
|
border-color: #DF421E;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.CAUTION td,
|
||||||
|
table.CAUTION th,
|
||||||
|
table.WARNING td,
|
||||||
|
table.WARNING th {
|
||||||
|
border-width: 0;
|
||||||
|
padding-left: 2ex;
|
||||||
|
padding-right: 2ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.CAUTION td,
|
||||||
|
table.CAUTION th {
|
||||||
|
border-color: #F3E4D5
|
||||||
|
}
|
||||||
|
|
||||||
|
table.WARNING td,
|
||||||
|
table.WARNING th {
|
||||||
|
border-color: #FFD7D7;
|
||||||
|
}
|
||||||
|
|
||||||
|
td.c1,
|
||||||
|
td.c2,
|
||||||
|
td.c3,
|
||||||
|
td.c4,
|
||||||
|
td.c5,
|
||||||
|
td.c6 {
|
||||||
|
font-size: 1.1em;
|
||||||
|
font-weight: bold;
|
||||||
|
border-bottom: 0px solid #FFEFEF;
|
||||||
|
padding: 1ex 2ex 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Link Styles */
|
||||||
|
|
||||||
|
#docNav a {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:link,
|
||||||
|
a:visited,
|
||||||
|
a:active,
|
||||||
|
a:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:link,
|
||||||
|
a:active {
|
||||||
|
color:#0066A2;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:visited {
|
||||||
|
color:#004E66;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:hover {
|
||||||
|
color:#000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
#docFooter a:link,
|
||||||
|
#docFooter a:visited,
|
||||||
|
#docFooter a:active {
|
||||||
|
color:#666;
|
||||||
|
}
|
||||||
|
|
||||||
|
#docContainer code.FUNCTION tt {
|
||||||
|
font-size: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.header {
|
||||||
|
color: #444;
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.footer {
|
||||||
|
text-align: center;
|
||||||
|
background-image: url("/resources/footerl.png"), url("/resources/footerr.png"), url("/resources/footerc.png");
|
||||||
|
background-position: left top, right top, center top;
|
||||||
|
background-repeat: no-repeat, no-repeat, repeat-x;
|
||||||
|
padding-top: 45px;
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
border-style: none;
|
||||||
|
}
|
||||||
@@ -1,25 +1,2 @@
|
|||||||
/*
|
|
||||||
* repmgr_version.h
|
|
||||||
* Copyright (c) 2ndQuadrant, 2010-2017
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _VERSION_H_
|
|
||||||
#define _VERSION_H_
|
|
||||||
|
|
||||||
#define REPMGR_VERSION_DATE ""
|
#define REPMGR_VERSION_DATE ""
|
||||||
#define REPMGR_VERSION "4.0dev"
|
#define REPMGR_VERSION "4.0dev"
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|||||||
Reference in New Issue
Block a user