mirror of
https://github.com/EnterpriseDB/repmgr.git
synced 2026-03-23 15:16:29 +00:00
Compare commits
843 Commits
REL4_0_BET
...
REL4_3_STA
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ef382dfede | ||
|
|
bc93d2996c | ||
|
|
0946073406 | ||
|
|
129c8782a4 | ||
|
|
5493055a1d | ||
|
|
a50f0e7cc0 | ||
|
|
adfde1b681 | ||
|
|
d4b17635fe | ||
|
|
e4c573a7f6 | ||
|
|
492665e34c | ||
|
|
2d7c38e2ef | ||
|
|
9ee2448583 | ||
|
|
cf9458161f | ||
|
|
67dc42d2ad | ||
|
|
3b96b2afce | ||
|
|
216f274c15 | ||
|
|
8cb101be1d | ||
|
|
03b29908e2 | ||
|
|
99be03f000 | ||
|
|
7aaac343f8 | ||
|
|
68470a9167 | ||
|
|
35320c27bd | ||
|
|
b7b9db7e9c | ||
|
|
01e11950a5 | ||
|
|
fcaee6e6e8 | ||
|
|
538d5f9df0 | ||
|
|
4e8b94c105 | ||
|
|
9ee51bb0cb | ||
|
|
bab07cdda1 | ||
|
|
b03f07ca8f | ||
|
|
39fbe02c48 | ||
|
|
2249b79811 | ||
|
|
bb0fd944ae | ||
|
|
b4ca6851ab | ||
|
|
347948b79f | ||
|
|
83e492d4ef | ||
|
|
1906ea89bd | ||
|
|
eab4fd2795 | ||
|
|
3f1fe9b6c2 | ||
|
|
e672f7e3ee | ||
|
|
fd86160dff | ||
|
|
f19cf62f09 | ||
|
|
8018ba97d6 | ||
|
|
73554c6e16 | ||
|
|
f23a93e12d | ||
|
|
d9947a46e8 | ||
|
|
e3a632e29d | ||
|
|
939cbd0721 | ||
|
|
c45c5abfb8 | ||
|
|
1953ec7459 | ||
|
|
a6eacca6e4 | ||
|
|
948e076ad9 | ||
|
|
a3bd9d33ff | ||
|
|
9dc928a7d5 | ||
|
|
9acf7bdfea | ||
|
|
29acd10f37 | ||
|
|
9df511eee3 | ||
|
|
6441db23ff | ||
|
|
7792de3543 | ||
|
|
94fe3e395e | ||
|
|
ff26173b1e | ||
|
|
4c11a57334 | ||
|
|
1d2d6e3587 | ||
|
|
c03913d32a | ||
|
|
37a41a66f9 | ||
|
|
4c2c8ecbab | ||
|
|
b84b6180ee | ||
|
|
58f55222d9 | ||
|
|
5cbaff8d0a | ||
|
|
a38e229e61 | ||
|
|
272abdd483 | ||
|
|
b4f6043abc | ||
|
|
a7f3f899ff | ||
|
|
3ec43eda36 | ||
|
|
ce8e1cccc4 | ||
|
|
70bfa4c8e1 | ||
|
|
f0d5ad503d | ||
|
|
b9ee57ee0f | ||
|
|
d5d6ed4be7 | ||
|
|
f4655074ae | ||
|
|
67d26ab7e2 | ||
|
|
70a7b45a03 | ||
|
|
4251590833 | ||
|
|
9347d34ce0 | ||
|
|
feb90ee50c | ||
|
|
0a6486bb7f | ||
|
|
39443bbcee | ||
|
|
fc636b1bd2 | ||
|
|
048bad1c88 | ||
|
|
4528eb1796 | ||
|
|
169c9ccd32 | ||
|
|
5f92fbddf2 | ||
|
|
617e466f72 | ||
|
|
435fac297b | ||
|
|
4bc12b4c94 | ||
|
|
91234994e2 | ||
|
|
ee9da30f20 | ||
|
|
2e67bc1341 | ||
|
|
18ab5cab4e | ||
|
|
60bb4e9fc8 | ||
|
|
52bee6b98d | ||
|
|
ecb1f379f5 | ||
|
|
e1cd2c22d4 | ||
|
|
1dea6b76d9 | ||
|
|
702f90fc9d | ||
|
|
c4d1eec6f3 | ||
|
|
b241c606c0 | ||
|
|
45c896d716 | ||
|
|
514595ea10 | ||
|
|
531194fa27 | ||
|
|
2aa67c992c | ||
|
|
37892afcfc | ||
|
|
e4e5e35552 | ||
|
|
b320c1f0ae | ||
|
|
280654bed6 | ||
|
|
ae675059c0 | ||
|
|
454ebabe89 | ||
|
|
d1d6ef8d12 | ||
|
|
5d6eab74f6 | ||
|
|
59b7453bbf | ||
|
|
bde8c7e29c | ||
|
|
bc6584a90d | ||
|
|
074d79b44f | ||
|
|
2eeb288573 | ||
|
|
48a2274b11 | ||
|
|
19bcfa7264 | ||
|
|
486877c3d5 | ||
|
|
9753bcc8c3 | ||
|
|
bd35b450da | ||
|
|
1f256d4d73 | ||
|
|
1524e2449f | ||
|
|
0cd2bd2e91 | ||
|
|
98b78df16c | ||
|
|
b946dce2f0 | ||
|
|
39234afcbf | ||
|
|
23569a19b1 | ||
|
|
c650fd3412 | ||
|
|
c30e65b3f2 | ||
|
|
07097575b1 | ||
|
|
71d151ca87 | ||
|
|
5abec2bb97 | ||
|
|
de70fd42dc | ||
|
|
99550b91bd | ||
|
|
70190c37c4 | ||
|
|
f3fc4e5afb | ||
|
|
629c552348 | ||
|
|
85a97c933f | ||
|
|
3a5a4388c7 | ||
|
|
9338a9e233 | ||
|
|
7fad2ed2c8 | ||
|
|
9305953bd2 | ||
|
|
aeb9639ed9 | ||
|
|
bc9e725d05 | ||
|
|
905e108f8f | ||
|
|
f2362a06fa | ||
|
|
7b85cb9f12 | ||
|
|
790bec21dd | ||
|
|
a0dc673439 | ||
|
|
25019d1cc5 | ||
|
|
d00cb767a6 | ||
|
|
8e0d28d8dc | ||
|
|
e146fb4fc3 | ||
|
|
8773543e10 | ||
|
|
a4cd4ee553 | ||
|
|
a61dd8a750 | ||
|
|
2c84716e66 | ||
|
|
f1667a7e98 | ||
|
|
b91900f831 | ||
|
|
aa1e64ec11 | ||
|
|
5d6037303b | ||
|
|
8aaf6571a0 | ||
|
|
9433f80364 | ||
|
|
aee13aee52 | ||
|
|
f0a0be0248 | ||
|
|
c4332d9a52 | ||
|
|
c7b325e2a4 | ||
|
|
b89941f218 | ||
|
|
2b3b1faa20 | ||
|
|
b9cd321aed | ||
|
|
984ce7420b | ||
|
|
464ec6bec3 | ||
|
|
3bbbf6daa9 | ||
|
|
cd3312496e | ||
|
|
cce8b76171 | ||
|
|
2a529e7e8b | ||
|
|
f62b3b2868 | ||
|
|
701944c194 | ||
|
|
d8048060a2 | ||
|
|
31f25856a2 | ||
|
|
92c73b68a0 | ||
|
|
90909e2e42 | ||
|
|
b036870c83 | ||
|
|
321eb844e4 | ||
|
|
2c9700586c | ||
|
|
f9a1861ded | ||
|
|
59ed86c01a | ||
|
|
f24b30327c | ||
|
|
48381a5b4e | ||
|
|
20b79f998c | ||
|
|
a41e7bb726 | ||
|
|
b9ba97a36d | ||
|
|
d8aa472c5f | ||
|
|
9273e7af73 | ||
|
|
f04f2af8aa | ||
|
|
bdb4f66a9d | ||
|
|
c402b08791 | ||
|
|
64bb034d34 | ||
|
|
ea54aaa290 | ||
|
|
b34c331eba | ||
|
|
19e0b6a1b6 | ||
|
|
9349171b55 | ||
|
|
d4ee4cc14c | ||
|
|
d7420d7274 | ||
|
|
70e4243a1d | ||
|
|
b6264b77c4 | ||
|
|
9e7cb6d01c | ||
|
|
0435bda115 | ||
|
|
a5aa47c1dd | ||
|
|
7654dd615b | ||
|
|
c83e9870fe | ||
|
|
8b13d14294 | ||
|
|
ba13172b3a | ||
|
|
32b81e7d49 | ||
|
|
cbfef17a1d | ||
|
|
a48d408e4e | ||
|
|
e5f50e7b99 | ||
|
|
aeea02b598 | ||
|
|
59eca2be30 | ||
|
|
dfe57d2406 | ||
|
|
061932d023 | ||
|
|
3f5762e03a | ||
|
|
42fa9a2a88 | ||
|
|
f23065e041 | ||
|
|
efe4a9c344 | ||
|
|
0970789b1d | ||
|
|
07b79286b5 | ||
|
|
c3d284e097 | ||
|
|
a9e09d436a | ||
|
|
965984a510 | ||
|
|
1980deb480 | ||
|
|
b6fe91ebcd | ||
|
|
44cbb44500 | ||
|
|
99161c38d2 | ||
|
|
57d3ee768c | ||
|
|
7dce3ed234 | ||
|
|
58efb0f158 | ||
|
|
d261768541 | ||
|
|
aa8547a219 | ||
|
|
9f04a846ec | ||
|
|
ff0e480fdd | ||
|
|
8881b69c06 | ||
|
|
0b3a310802 | ||
|
|
4523137bfc | ||
|
|
666f5cf851 | ||
|
|
e89938e132 | ||
|
|
d97905f6fd | ||
|
|
bed66edfd9 | ||
|
|
ba7ef9e643 | ||
|
|
10be941298 | ||
|
|
75379eab2e | ||
|
|
d4e993a240 | ||
|
|
695a45f9ed | ||
|
|
028c874f81 | ||
|
|
b3c2831bd3 | ||
|
|
e191a32eac | ||
|
|
c66c8ebc98 | ||
|
|
3389491151 | ||
|
|
81eb9d99e7 | ||
|
|
1156f27979 | ||
|
|
b5b9aacc8a | ||
|
|
b89b3c0961 | ||
|
|
9cf5bf3f93 | ||
|
|
9a5bd0d489 | ||
|
|
40408a1734 | ||
|
|
40410e43ab | ||
|
|
3c25d5a03a | ||
|
|
7e21ceb158 | ||
|
|
313aa3c5d7 | ||
|
|
10d46f7e85 | ||
|
|
9e90fcd584 | ||
|
|
c53782cda3 | ||
|
|
66b40ffc68 | ||
|
|
a6a2be2239 | ||
|
|
bdcc4d9e83 | ||
|
|
9f587efb74 | ||
|
|
2aacd29e60 | ||
|
|
311f7e561e | ||
|
|
b498db87aa | ||
|
|
74c44a7178 | ||
|
|
5ff3744895 | ||
|
|
793d83b22c | ||
|
|
0f4e04e61e | ||
|
|
80a280cbf4 | ||
|
|
b223cb4cee | ||
|
|
9d1f5c0de3 | ||
|
|
784c9c4793 | ||
|
|
0caec90d81 | ||
|
|
1458f6e6aa | ||
|
|
a2d38c6084 | ||
|
|
5f1bf0fb8f | ||
|
|
7d99b96717 | ||
|
|
3b10750a7f | ||
|
|
af0a60b8eb | ||
|
|
b419c5fec7 | ||
|
|
2cfcc33a64 | ||
|
|
273db444b2 | ||
|
|
2bf3eeb931 | ||
|
|
c3bc5585d9 | ||
|
|
b84f217710 | ||
|
|
90c49c0c28 | ||
|
|
41c1550788 | ||
|
|
c336e384ab | ||
|
|
bc1956dee9 | ||
|
|
a459c60145 | ||
|
|
65721bbbcd | ||
|
|
96895ba8a8 | ||
|
|
e0d6d906e7 | ||
|
|
dc8ffd30c6 | ||
|
|
24392fa11b | ||
|
|
06b5239ada | ||
|
|
56173d94a9 | ||
|
|
578f11003c | ||
|
|
36bd7cdc9f | ||
|
|
62ac56c3f5 | ||
|
|
c79852cce0 | ||
|
|
3907a545b0 | ||
|
|
d1d057a184 | ||
|
|
b70e3b48c8 | ||
|
|
ab6c3d9b6e | ||
|
|
6999dbb52a | ||
|
|
b2348c9a70 | ||
|
|
7b26180ebb | ||
|
|
d70a5250ab | ||
|
|
024accfbba | ||
|
|
55c967fd14 | ||
|
|
c1edb896df | ||
|
|
fd66d93937 | ||
|
|
40e94635b2 | ||
|
|
9ad41bfb0f | ||
|
|
35c156ce7e | ||
|
|
85f27ff559 | ||
|
|
ad03885b72 | ||
|
|
3e38759c02 | ||
|
|
15a5d2ee9d | ||
|
|
61c91df332 | ||
|
|
b346914d4d | ||
|
|
ac40ef0e43 | ||
|
|
eebf07549f | ||
|
|
a40fd60cb5 | ||
|
|
bd24848ce9 | ||
|
|
7ab81e10de | ||
|
|
455a0bd93f | ||
|
|
11d25e2aef | ||
|
|
b14fbbdc72 | ||
|
|
2491b8ae52 | ||
|
|
fce3c02760 | ||
|
|
1f8f6f3a39 | ||
|
|
401f903456 | ||
|
|
688337dec3 | ||
|
|
b660cb9fe4 | ||
|
|
5d8d9db21d | ||
|
|
9439467958 | ||
|
|
38e3aae053 | ||
|
|
80bef0eb28 | ||
|
|
bea4b03cc2 | ||
|
|
97905b02ae | ||
|
|
b0a2ee2259 | ||
|
|
bb4fdcda98 | ||
|
|
7b33faa09b | ||
|
|
5de2b1ee13 | ||
|
|
f184b1e68a | ||
|
|
bd2f6db1e1 | ||
|
|
1693ec0e90 | ||
|
|
17e75f6b31 | ||
|
|
3b8586d82a | ||
|
|
6acec3e041 | ||
|
|
1d830bf0e2 | ||
|
|
3f99ee8ede | ||
|
|
b5f640d04d | ||
|
|
92a62a958e | ||
|
|
a4a956593c | ||
|
|
ceeb6d7130 | ||
|
|
9681708b1a | ||
|
|
3573950425 | ||
|
|
c1586e39b7 | ||
|
|
7745844078 | ||
|
|
e1e59e85d7 | ||
|
|
6fc79470fc | ||
|
|
b7d576863d | ||
|
|
c1338df5e3 | ||
|
|
221fb63e92 | ||
|
|
987823861f | ||
|
|
7a6eb6321b | ||
|
|
f4df6696ba | ||
|
|
bc584d84f6 | ||
|
|
76f5bcf3cd | ||
|
|
b1aab930af | ||
|
|
58994365ff | ||
|
|
c3949b2aea | ||
|
|
6ba49de44e | ||
|
|
b61f853a69 | ||
|
|
f2bc898761 | ||
|
|
7bcf87b8ed | ||
|
|
6983547325 | ||
|
|
34c4f4c3f8 | ||
|
|
f8667c1aac | ||
|
|
08ab6290c1 | ||
|
|
97cafd8c54 | ||
|
|
78b969f208 | ||
|
|
3f558416f3 | ||
|
|
410fa5e54d | ||
|
|
44a224ad92 | ||
|
|
33dedf4e96 | ||
|
|
4f4d20c30b | ||
|
|
69cb87322d | ||
|
|
4351836520 | ||
|
|
a87f18682c | ||
|
|
1a630d079e | ||
|
|
d2929f6426 | ||
|
|
f3f002bea5 | ||
|
|
93471b8d68 | ||
|
|
46e0a9a8db | ||
|
|
3620fa79e8 | ||
|
|
c236405251 | ||
|
|
527a5f7fee | ||
|
|
937cffd54c | ||
|
|
2b1e12591a | ||
|
|
7ecfb333b9 | ||
|
|
8f13a66aaa | ||
|
|
ef35d071bf | ||
|
|
b87f9dabb4 | ||
|
|
7decc7975f | ||
|
|
a5cfc244bc | ||
|
|
673bde2b7f | ||
|
|
81de200561 | ||
|
|
cb46fb6410 | ||
|
|
bd58e4128c | ||
|
|
63242e2277 | ||
|
|
69782cf703 | ||
|
|
5acb3e6790 | ||
|
|
6dfcaa357e | ||
|
|
8acc50e752 | ||
|
|
56919ea499 | ||
|
|
b3f64987cb | ||
|
|
388ac2f392 | ||
|
|
8b059bc9b0 | ||
|
|
cfa7155784 | ||
|
|
47644b55ed | ||
|
|
17f30ec364 | ||
|
|
c6b8d78bad | ||
|
|
ae60caacdd | ||
|
|
92d0e6809b | ||
|
|
4c7c681a14 | ||
|
|
29de052dd8 | ||
|
|
ebf2a3a7cc | ||
|
|
37311e15a3 | ||
|
|
a194cf56b3 | ||
|
|
c4f9205f17 | ||
|
|
6d09ebcfb5 | ||
|
|
319a29583d | ||
|
|
a5d47fd478 | ||
|
|
190104c7db | ||
|
|
ff16d3b3bb | ||
|
|
802755fd60 | ||
|
|
d00c0c67d0 | ||
|
|
8d636690bd | ||
|
|
b2081dca52 | ||
|
|
080a29c33b | ||
|
|
dd7a4068d2 | ||
|
|
fcf237fe31 | ||
|
|
4d70a667fb | ||
|
|
c5ba72c2c5 | ||
|
|
0f97a98f28 | ||
|
|
269e3242c8 | ||
|
|
b0ed87832b | ||
|
|
836d2125fe | ||
|
|
bf0d67c60a | ||
|
|
e1d807188d | ||
|
|
108c3a36fb | ||
|
|
8377704596 | ||
|
|
4f642f8332 | ||
|
|
029ba46470 | ||
|
|
098f8eaf2a | ||
|
|
d60bd232f0 | ||
|
|
eca1943026 | ||
|
|
bcab4bc391 | ||
|
|
bb320a64f5 | ||
|
|
3b0cde2846 | ||
|
|
00704913a6 | ||
|
|
efc388065e | ||
|
|
e12fbb7b4d | ||
|
|
0108fb2e72 | ||
|
|
e408351697 | ||
|
|
f904cd2573 | ||
|
|
95fe7ea621 | ||
|
|
a50ac039da | ||
|
|
535fba43d3 | ||
|
|
043a6c5bea | ||
|
|
8da26f1c6c | ||
|
|
7861392450 | ||
|
|
b297e40d77 | ||
|
|
7613b1769c | ||
|
|
b1b49748a7 | ||
|
|
276239422b | ||
|
|
49418e096e | ||
|
|
6c518f1403 | ||
|
|
b365765bc8 | ||
|
|
bd63948937 | ||
|
|
69c1f147ea | ||
|
|
ce8d3cf0b0 | ||
|
|
14134f8e70 | ||
|
|
be8448ddcb | ||
|
|
a2ff1536ad | ||
|
|
9c0c1b663e | ||
|
|
2d43feb34b | ||
|
|
6f315c1b3c | ||
|
|
635bdccb2c | ||
|
|
16048a879e | ||
|
|
eac80ae9c1 | ||
|
|
887b845aa0 | ||
|
|
8320179f34 | ||
|
|
7822aa784f | ||
|
|
4455ded935 | ||
|
|
fd0b850f41 | ||
|
|
d9ac1d6fd0 | ||
|
|
11e4d9fd05 | ||
|
|
4b54106f48 | ||
|
|
f3941ceab0 | ||
|
|
93f80c413e | ||
|
|
09b8a86605 | ||
|
|
6b3d54a5f3 | ||
|
|
85ab2d94b7 | ||
|
|
cda952f1e4 | ||
|
|
99ad57f88a | ||
|
|
ad0671ead2 | ||
|
|
1bbb2ef213 | ||
|
|
62c29aab32 | ||
|
|
b9dc94f28f | ||
|
|
e8ba213174 | ||
|
|
0dcddbb062 | ||
|
|
b4dab86c3b | ||
|
|
644a56a645 | ||
|
|
4876a9fde3 | ||
|
|
ec998bf9c5 | ||
|
|
e36b180de8 | ||
|
|
a2068768ab | ||
|
|
bde9fea48c | ||
|
|
cdaf84c329 | ||
|
|
c4cd0c46da | ||
|
|
3b00dc912a | ||
|
|
1a80de1290 | ||
|
|
26b565dff2 | ||
|
|
96811ccc01 | ||
|
|
73982859f6 | ||
|
|
afb7ca886c | ||
|
|
df11ad894f | ||
|
|
614b4ae84b | ||
|
|
1e1b4b1a65 | ||
|
|
cf64f9e95c | ||
|
|
dfdebd6c08 | ||
|
|
63a11f8926 | ||
|
|
a3f371b8c0 | ||
|
|
938692c169 | ||
|
|
ad24b04c35 | ||
|
|
3ccf1cf182 | ||
|
|
5e4bdb5a1b | ||
|
|
50321bb95d | ||
|
|
253c215c12 | ||
|
|
22c40ae62d | ||
|
|
239a548e9d | ||
|
|
231ef5563e | ||
|
|
e1413fa8ea | ||
|
|
7111483b65 | ||
|
|
1558497ae4 | ||
|
|
9c5e76401f | ||
|
|
a403da67bc | ||
|
|
71b13f5307 | ||
|
|
1c5561d114 | ||
|
|
c0b607ef41 | ||
|
|
462fdca4b4 | ||
|
|
0e55a60660 | ||
|
|
93deab3e96 | ||
|
|
81c69e3677 | ||
|
|
0219f4c91f | ||
|
|
85a4adc99c | ||
|
|
208d7d418e | ||
|
|
7cb6e5af8d | ||
|
|
d2a2df13d5 | ||
|
|
358e001218 | ||
|
|
d7702b3444 | ||
|
|
a8286030c0 | ||
|
|
ff0ba3e19a | ||
|
|
6f5cce7e6f | ||
|
|
509f7a8255 | ||
|
|
e8cdf72ecd | ||
|
|
2a99dfa15b | ||
|
|
bad034f7ee | ||
|
|
cdb504d700 | ||
|
|
0af2077bed | ||
|
|
dea87b7285 | ||
|
|
d6b13f3428 | ||
|
|
5808d8190e | ||
|
|
d2a5cc23cc | ||
|
|
9981ede1af | ||
|
|
40ccae57a3 | ||
|
|
3c2b8e5792 | ||
|
|
354231284e | ||
|
|
dbbfcb6a63 | ||
|
|
bc766a48ed | ||
|
|
55441f2729 | ||
|
|
e38a9ec7e1 | ||
|
|
c1356b9e0d | ||
|
|
383a17fba1 | ||
|
|
29cb153643 | ||
|
|
15625183c1 | ||
|
|
b6a1b75d22 | ||
|
|
c644ddde51 | ||
|
|
ee98a3a58e | ||
|
|
22b3a74fa0 | ||
|
|
98af51da03 | ||
|
|
e5eff3f6d5 | ||
|
|
728a256a93 | ||
|
|
f5f02ae0ee | ||
|
|
64d85587de | ||
|
|
6b7f6089ba | ||
|
|
5719a0dfd3 | ||
|
|
927bf038a0 | ||
|
|
76a93af15c | ||
|
|
ee2df36a76 | ||
|
|
571e6b2783 | ||
|
|
76cc11b786 | ||
|
|
56710f4819 | ||
|
|
f9528efdb8 | ||
|
|
658ec20e37 | ||
|
|
e6aa831782 | ||
|
|
9b56f157dc | ||
|
|
05f872effe | ||
|
|
ae691688be | ||
|
|
57f1e939c5 | ||
|
|
48b5deebf3 | ||
|
|
1868453953 | ||
|
|
dd45189fa8 | ||
|
|
a79c4fae88 | ||
|
|
657ed83921 | ||
|
|
4fb085f52d | ||
|
|
d0bb5b1565 | ||
|
|
ee64f3a745 | ||
|
|
6c81e54f76 | ||
|
|
65bf203a89 | ||
|
|
b4dbee517f | ||
|
|
e23d28a22d | ||
|
|
811d2a45bd | ||
|
|
92f4710ee2 | ||
|
|
044d8a1098 | ||
|
|
b38f45120c | ||
|
|
db3a046393 | ||
|
|
ec068e38a2 | ||
|
|
3a382e826e | ||
|
|
3dcf57a333 | ||
|
|
f658c8d3d8 | ||
|
|
375a96a5c8 | ||
|
|
b4d6724405 | ||
|
|
8fd0c4ad83 | ||
|
|
7ccae6c2b1 | ||
|
|
61d46172b9 | ||
|
|
810471b2f2 | ||
|
|
5bd8cf958a | ||
|
|
5a45997db5 | ||
|
|
f1f5100007 | ||
|
|
1c8ad4d89b | ||
|
|
842a610e84 | ||
|
|
fcb7e7a29b | ||
|
|
26e404b1f3 | ||
|
|
625d032435 | ||
|
|
3d07d65966 | ||
|
|
b705127a34 | ||
|
|
832b38c5cb | ||
|
|
3739a7b84d | ||
|
|
841f03aeba | ||
|
|
cad12b1fb7 | ||
|
|
d31cc80d26 | ||
|
|
625187a61e | ||
|
|
e64d965c6a | ||
|
|
5d8ec136e6 | ||
|
|
9951a8e106 | ||
|
|
26a9e848fd | ||
|
|
ba0b0a497f | ||
|
|
09dc43a61c | ||
|
|
b349f82571 | ||
|
|
adbb627850 | ||
|
|
c47f976bde | ||
|
|
7c8cd7a482 | ||
|
|
edce8addbd | ||
|
|
b0f6202448 | ||
|
|
985b13b6d3 | ||
|
|
69e64a9464 | ||
|
|
f58954b3be | ||
|
|
3761d17752 | ||
|
|
8c121da8a1 | ||
|
|
6e9e4543e8 | ||
|
|
c94f1b7338 | ||
|
|
f78c169c3d | ||
|
|
f2db9f3ea4 | ||
|
|
9944324c3a | ||
|
|
836f32bdbc | ||
|
|
cebbc73c38 | ||
|
|
472d703d2e | ||
|
|
de34e4e89b | ||
|
|
3a8ee126f3 | ||
|
|
da93dd1f57 | ||
|
|
295c18f6ff | ||
|
|
81beec54aa | ||
|
|
2e42226f68 | ||
|
|
de10d7984a | ||
|
|
404aab4041 | ||
|
|
8c422d6084 | ||
|
|
8b78b7292d | ||
|
|
4cebba32e2 | ||
|
|
c9f12cfbe0 | ||
|
|
5b4c92392c | ||
|
|
e2b94adec3 | ||
|
|
3164bfa043 | ||
|
|
08b443dce0 | ||
|
|
9165d27f9f | ||
|
|
b8b991398a | ||
|
|
a9a17f206e | ||
|
|
9d432546bf | ||
|
|
3c557ebd8e | ||
|
|
4efeb52cba | ||
|
|
60422c66f9 | ||
|
|
b63872afbb | ||
|
|
a31980b590 | ||
|
|
e07a3c7976 | ||
|
|
9d9a1be062 | ||
|
|
8208b3f844 | ||
|
|
ecb8297b1f | ||
|
|
1553596f84 | ||
|
|
022d9c58c2 | ||
|
|
a6cc4d80f0 | ||
|
|
7fffe3ed96 | ||
|
|
9b93a595f5 | ||
|
|
c34e08b802 | ||
|
|
eb14bb58c6 | ||
|
|
aa28069d8b | ||
|
|
a1e272f64c | ||
|
|
9908a9c662 | ||
|
|
aa089820ab | ||
|
|
0230bafae1 | ||
|
|
de577adc67 | ||
|
|
fed17d49e3 | ||
|
|
d80763f974 | ||
|
|
331e982bdb | ||
|
|
4ca7e6a6bf | ||
|
|
6ac6e0733a | ||
|
|
79d21b516b | ||
|
|
7232187f4d | ||
|
|
fe98270b3f | ||
|
|
5a3e20fc38 | ||
|
|
4ef2b111da | ||
|
|
97471626b4 | ||
|
|
4bd236b64c | ||
|
|
615dd2ecf4 | ||
|
|
1c1887f9cc | ||
|
|
d3f11a640d | ||
|
|
2341da7a06 | ||
|
|
2c468d64fb | ||
|
|
9d9b74d740 | ||
|
|
a90d4419a6 | ||
|
|
68756c79f3 | ||
|
|
8ad081e7b5 | ||
|
|
6b76704817 | ||
|
|
c03c509e73 | ||
|
|
d9db4f6c45 | ||
|
|
c89d59fe96 | ||
|
|
02b6d3748b | ||
|
|
7c3abe28b9 | ||
|
|
a39b8ccc2d | ||
|
|
5638d4ab89 | ||
|
|
37bdad290c | ||
|
|
8911434da5 | ||
|
|
8a2bbcebfd | ||
|
|
61f01f8305 | ||
|
|
a35d77b7f0 | ||
|
|
40ea1abbb4 | ||
|
|
785bfe9837 | ||
|
|
31cd54bcff | ||
|
|
35c8bb4e75 | ||
|
|
6b9ac22029 | ||
|
|
7bf3c78f57 | ||
|
|
34ee16899e | ||
|
|
0938685ae7 | ||
|
|
b400436fba | ||
|
|
2745c92fc8 | ||
|
|
34c0131b2d | ||
|
|
c9abfdcc04 | ||
|
|
a878d7aaea | ||
|
|
93aa7cea1a | ||
|
|
f00e6296e9 | ||
|
|
91354a71cc | ||
|
|
c78cb6e1d6 | ||
|
|
71430a9f65 | ||
|
|
3e93f847fd | ||
|
|
0b2a6fe2fb | ||
|
|
e716d09053 | ||
|
|
f885e105f2 | ||
|
|
43be854ec6 | ||
|
|
f7e2c700b1 | ||
|
|
b1eef0a212 | ||
|
|
39e8a560b0 | ||
|
|
d4a847a96f | ||
|
|
034e501039 | ||
|
|
08878831fe | ||
|
|
cf1e17d758 | ||
|
|
87ea7850ca | ||
|
|
fee4569887 | ||
|
|
a4e79d33af | ||
|
|
a480b8bd52 | ||
|
|
d156de533d | ||
|
|
da47eb4bff | ||
|
|
5fd823fda9 | ||
|
|
c5c27d2250 | ||
|
|
ec843e1de4 | ||
|
|
e18d6ea81f | ||
|
|
cb61b447f3 | ||
|
|
9697e2ccfc | ||
|
|
e7bb3e9d50 | ||
|
|
f1fe6a32fc | ||
|
|
a149a99228 | ||
|
|
5fffd177a4 | ||
|
|
8013634b79 | ||
|
|
8d609249fd | ||
|
|
2f4e7c1d8b | ||
|
|
244d36a7d6 | ||
|
|
9a94878c73 | ||
|
|
4ab081ba41 | ||
|
|
aaf5af7591 | ||
|
|
2a48edb625 | ||
|
|
b049d7f0ec | ||
|
|
bb35ee1750 | ||
|
|
caa8d034de | ||
|
|
0c64b90427 | ||
|
|
d8c2f66c5b | ||
|
|
e00b4461b3 |
7
.gitignore
vendored
7
.gitignore
vendored
@@ -39,10 +39,17 @@ lib*.pc
|
|||||||
|
|
||||||
# test output
|
# test output
|
||||||
/results/
|
/results/
|
||||||
|
/regression.diffs
|
||||||
|
/regression.out
|
||||||
|
|
||||||
|
/doc/Makefile
|
||||||
|
|
||||||
# other
|
# other
|
||||||
/.lineno
|
/.lineno
|
||||||
*.dSYM
|
*.dSYM
|
||||||
|
*.orig
|
||||||
|
*.rej
|
||||||
|
|
||||||
# generated binaries
|
# generated binaries
|
||||||
repmgr
|
repmgr
|
||||||
repmgrd
|
repmgrd
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ License and Contributions
|
|||||||
=========================
|
=========================
|
||||||
|
|
||||||
`repmgr` is licensed under the GPL v3. All of its code and documentation is
|
`repmgr` is licensed under the GPL v3. All of its code and documentation is
|
||||||
Copyright 2010-2017, 2ndQuadrant Limited. See the files COPYRIGHT and LICENSE for
|
Copyright 2010-2019, 2ndQuadrant Limited. See the files COPYRIGHT and LICENSE for
|
||||||
details.
|
details.
|
||||||
|
|
||||||
The development of repmgr has primarily been sponsored by 2ndQuadrant customers.
|
The development of repmgr has primarily been sponsored by 2ndQuadrant customers.
|
||||||
@@ -24,8 +24,7 @@ Code style
|
|||||||
Code in repmgr should be formatted to the same standards as the main PostgreSQL
|
Code in repmgr should be formatted to the same standards as the main PostgreSQL
|
||||||
project. For more details see:
|
project. For more details see:
|
||||||
|
|
||||||
https://www.postgresql.org/docs/current/static/source-format.html
|
https://www.postgresql.org/docs/current/source-format.html
|
||||||
|
|
||||||
Contributors should reformat their code similarly before submitting code to
|
Contributors should reformat their code similarly before submitting code to
|
||||||
the project, in order to minimize merge conflicts with other work.
|
the project, in order to minimize merge conflicts with other work.
|
||||||
>>>>>>> Add further documentation files
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
Copyright (c) 2010-2017, 2ndQuadrant Limited
|
Copyright (c) 2010-2019, 2ndQuadrant Limited
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
This program is free software: you can redistribute it and/or modify
|
||||||
@@ -12,5 +12,5 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see http://www.gnu.org/licenses/
|
along with this program. If not, see https://www.gnu.org/licenses/
|
||||||
to obtain one.
|
to obtain one.
|
||||||
|
|||||||
10
FAQ.md
Normal file
10
FAQ.md
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
FAQ - Frequently Asked Questions about repmgr
|
||||||
|
=============================================
|
||||||
|
|
||||||
|
The repmgr 4 FAQ is located here: [repmgr FAQ (Frequently Asked Questions)](https://repmgr.org/docs/current/appendix-faq.html "repmgr FAQ")
|
||||||
|
|
||||||
|
The repmgr 3.x FAQ can be found here:
|
||||||
|
|
||||||
|
https://github.com/2ndQuadrant/repmgr/blob/REL3_3_STABLE/FAQ.md
|
||||||
|
|
||||||
|
Note that repmgr 3.x is no longer supported.
|
||||||
480
HISTORY
480
HISTORY
@@ -1,2 +1,480 @@
|
|||||||
4.0 2017-09
|
4.3.1 2019-12-??
|
||||||
|
repmgr: ensure an existing replication slot is not deleted if the
|
||||||
|
follow target is the node's current upstream (Ian)
|
||||||
|
|
||||||
|
4.3 2019-04-02
|
||||||
|
repmgr: add "daemon (start|stop)" command; GitHub #528 (Ian)
|
||||||
|
repmgr: add --version-number command line option (Ian)
|
||||||
|
repmgr: add --compact option to "cluster show"; GitHub #521 (Ian)
|
||||||
|
repmgr: cluster show - differentiate between unreachable nodes
|
||||||
|
and nodes which are running but rejecting connections (Ian)
|
||||||
|
repmgr: add --dry-run option to "standby promote"; GitHub #522 (Ian)
|
||||||
|
repmgr: add "node check --data-directory-config"; GitHub #523 (Ian)
|
||||||
|
repmgr: prevent potential race condition in "standby switchover"
|
||||||
|
when checking received WAL location; GitHub #518 (Ian)
|
||||||
|
repmgr: ensure "standby switchover" verifies repmgr can read the
|
||||||
|
data directory on the demotion candidate; GitHub #523 (Ian)
|
||||||
|
repmgr: ensure "standby switchover" verifies replication connection
|
||||||
|
exists; GitHub #519 (Ian)
|
||||||
|
repmgr: add sanity check for correct extension version (Ian)
|
||||||
|
repmgr: ensure "witness register --dry-run" does not attempt to read node
|
||||||
|
tables if repmgr extension not installed; GitHub #513 (Ian)
|
||||||
|
repmgr: ensure "standby register" fails when --upstream-node-id is the
|
||||||
|
same as the local node ID (Ian)
|
||||||
|
repmgrd: check binary and extension major versions match; GitHub #515 (Ian)
|
||||||
|
repmgrd: on a cascaded standby, don't fail over if "failover=manual";
|
||||||
|
GitHub #531 (Ian)
|
||||||
|
repmgrd: don't consider nodes where repmgrd is not running as promotion
|
||||||
|
candidates (Ian)
|
||||||
|
repmgrd: add option "connection_check_type" (Ian)
|
||||||
|
repmgrd: improve witness monitoring when primary node not available (Ian)
|
||||||
|
repmgrd: handle situation where a primary has unexpectedly appeared
|
||||||
|
during failover; GitHub #420 (Ian)
|
||||||
|
general: fix Makefile (John)
|
||||||
|
|
||||||
|
4.2 2018-10-24
|
||||||
|
repmgr: add parameter "shutdown_check_timeout" for use by "standby switchover";
|
||||||
|
GitHub #504 (Ian)
|
||||||
|
repmgr: add "--node-id" option to "repmgr cluster cleanup"; GitHub #493 (Ian)
|
||||||
|
repmgr: report unreachable nodes when running "repmgr cluster (matrix|crosscheck);
|
||||||
|
GitHub #246 (Ian)
|
||||||
|
repmgr: add configuration file parameter "repmgr_bindir"; GitHub #246 (Ian)
|
||||||
|
repmgr: fix "Missing replication slots" label in "node check"; GitHub #507 (Ian)
|
||||||
|
repmgrd: fix parsing of -d/--daemonize option (Ian)
|
||||||
|
repmgrd: support "pausing" of repmgrd (Ian)
|
||||||
|
|
||||||
|
4.1.1 2018-09-05
|
||||||
|
logging: explicitly log the text of failed queries as ERRORs to
|
||||||
|
assist logfile analysis; GitHub #498
|
||||||
|
repmgr: truncate version string, if necessary; GitHub #490 (Ian)
|
||||||
|
repmgr: improve messages emitted during "standby promote" (Ian)
|
||||||
|
repmgr: "standby clone" - don't copy external config files in --dry-run
|
||||||
|
mode; GitHub #491 (Ian)
|
||||||
|
repmgr: add "cluster_cleanup" event; GitHub #492 (Ian)
|
||||||
|
repmgr: (standby switchover) improve detection of free walsenders;
|
||||||
|
GitHub #495 (Ian)
|
||||||
|
repmgr: (node rejoin) improve replication slot handling; GitHub #499 (Ian)
|
||||||
|
repmgrd: ensure that sending SIGHUP always results in the log file
|
||||||
|
being reopened; GitHub #485 (Ian)
|
||||||
|
repmgrd: report version number *after* logger initialisation; GitHub #487 (Ian)
|
||||||
|
repmgrd: fix startup on witness node when local data is stale; GitHub #488/#489 (Ian)
|
||||||
|
repmgrd: improve cascaded standby failover handling; GitHub #480 (Ian)
|
||||||
|
repmgrd: improve reconnection handling (Ian)
|
||||||
|
|
||||||
|
4.1.0 2018-07-31
|
||||||
|
repmgr: change default log_level to INFO, add documentation; GitHub #470 (Ian)
|
||||||
|
repmgr: add "--missing-slots" check to "repmgr node check" (Ian)
|
||||||
|
repmgr: improve command line error handling; GitHub #464 (Ian)
|
||||||
|
repmgr: fix "standby register --wait-sync" when no timeout provided (Ian)
|
||||||
|
repmgr: "cluster show" returns non-zero value if an issue encountered;
|
||||||
|
GitHub #456 (Ian)
|
||||||
|
repmgr: "node check" and "node status" returns non-zero value if an issue
|
||||||
|
encountered (Ian)
|
||||||
|
repmgr: add CSV output mode to "cluster event"; GitHub #471 (Ian)
|
||||||
|
repmgr: add -q/--quiet option to suppress non-error output; GitHub #468 (Ian)
|
||||||
|
repmgr: "node status" returns non-zero value if an issue encountered (Ian)
|
||||||
|
repmgr: enable "recovery_min_apply_delay" to be 0; GitHub #448 (Ian)
|
||||||
|
repmgr: "cluster cleanup" - add missing help options; GitHub #461/#462 (gclough)
|
||||||
|
repmgr: ensure witness node follows new primary after switchover;
|
||||||
|
GitHub #453 (Ian)
|
||||||
|
repmgr: fix witness node handling in "node check"/"node status";
|
||||||
|
GitHub #451 (Ian)
|
||||||
|
repmgr: fix "primary_slot_name" when using "standby clone" with --recovery-conf-only;
|
||||||
|
GitHub #474 (Ian)
|
||||||
|
repmgr: don't perform a switchover if an exclusive backup is running;
|
||||||
|
GitHub #476 (Martín)
|
||||||
|
repmgr: enable "witness unregister" to be run on any node; GitHub #472 (Ian)
|
||||||
|
repmgrd: create a PID file by default; GitHub #457 (Ian)
|
||||||
|
repmgrd: daemonize process by default; GitHub #458 (Ian)
|
||||||
|
|
||||||
|
4.0.6 2018-06-14
|
||||||
|
repmgr: (witness register) prevent registration of a witness server with the
|
||||||
|
same name as an existing node (Ian)
|
||||||
|
repmgr: (standby follow) check node has actually connected to new primary
|
||||||
|
before reporting success; GitHub #444 (Ian)
|
||||||
|
repmgr: (standby clone) improve handling of external configuration file copying,
|
||||||
|
including consideration in --dry-run check; GitHub #443 (Ian)
|
||||||
|
repmgr: (standby clone) don't require presence of "user" parameter in
|
||||||
|
conninfo string; GitHub #437 (Ian)
|
||||||
|
repmgr: (standby clone) improve documentation of --recovery-conf-only
|
||||||
|
mode; GitHub #438 (Ian)
|
||||||
|
repmgr: (node rejoin) fix bug when parsing --config-files parameter;
|
||||||
|
GitHub #442 (Ian)
|
||||||
|
repmgr: when using --dry-run, force log level to INFO to ensure output
|
||||||
|
will always be displayed; GitHub #441 (Ian)
|
||||||
|
repmgr: (cluster matrix/crosscheck) return non-zero exit code if node
|
||||||
|
connection issues detected; GitHub #447 (Ian)
|
||||||
|
repmgrd: ensure local node is counted as quorum member; GitHub #439 (Ian)
|
||||||
|
|
||||||
|
4.0.5 2018-05-02
|
||||||
|
repmgr: poll demoted primary after restart as a standby during a
|
||||||
|
switchover operation; GitHub #408 (Ian)
|
||||||
|
repmgr: add configuration parameter "config_directory"; GitHub #424 (Ian)
|
||||||
|
repmgr: add "dbname=replication" to all replication connection strings;
|
||||||
|
GitHub #421 (Ian)
|
||||||
|
repmgr: add sanity check if --upstream-node-id not supplied when executing
|
||||||
|
"standby register"; GitHub #395 (Ian)
|
||||||
|
repmgr: enable provision of "archive_cleanup_command" in recovery.conf;
|
||||||
|
GitHub #416 (Ian)
|
||||||
|
repmgr: actively check for node to rejoin cluster; GitHub #415 (Ian)
|
||||||
|
repmgr: enable pg_rewind to be used with PostgreSQL 9.3/9.4; GitHub #413 (Ian)
|
||||||
|
repmgr: fix minimum accepted value for "degraded_monitoring_timeout";
|
||||||
|
GitHub #411 (Ian)
|
||||||
|
repmgr: fix superuser password handling; GitHub #400 (Ian)
|
||||||
|
repmgr: fix parsing of "archive_ready_critical" configuration file
|
||||||
|
parameter; GitHub #426 (Ian)
|
||||||
|
repmgr: fix display of conninfo parsing error messages (Ian)
|
||||||
|
repmgr: fix "repmgr cluster crosscheck" output; GitHub #389 (Ian)
|
||||||
|
repmgrd: prevent standby connection handle from going stale (Ian)
|
||||||
|
repmgrd: fix memory leaks in witness code; GitHub #402 (AndrzejNowicki, Martín)
|
||||||
|
repmgrd: handle "pg_ctl promote" timeout; GitHub #425 (Ian)
|
||||||
|
repmgrd: handle failover situation with only two nodes in the primary
|
||||||
|
location, and at least one node in another location; GitHub #407 (Ian)
|
||||||
|
repmgrd: set "connect_timeout=2" when pinging a server (Ian)
|
||||||
|
|
||||||
|
4.0.4 2018-03-09
|
||||||
|
repmgr: add "standby clone --recovery-conf-only" option; GitHub #382 (Ian)
|
||||||
|
repmgr: make "standby promote" timeout values configurable; GitHub #387 (Ian)
|
||||||
|
repmgr: improve replication slot warnings generated by "node status";
|
||||||
|
GitHub #385 (Ian)
|
||||||
|
repmgr: remove restriction on replication slots when cloning from
|
||||||
|
a Barman server; GitHub #379 (Ian)
|
||||||
|
repmgr: ensure "node rejoin" honours "--dry-run" option; GitHub #383 (Ian)
|
||||||
|
repmgr: fix --superuser handling when cloning a standby; GitHub #380 (Ian)
|
||||||
|
repmgr: update various help options; GitHub #391, #392 (hasegeli)
|
||||||
|
repmgrd: add event "repmgrd_shutdown"; GitHub #393 (Ian)
|
||||||
|
repmgrd: improve detection of status change from primary to standby (Ian)
|
||||||
|
repmgrd: improve log output in various situations (Ian)
|
||||||
|
repmgrd: improve reconnection to the local node after a failover (Ian)
|
||||||
|
repmgrd: ensure witness server connects to new primary after a failover (Ian)
|
||||||
|
|
||||||
|
4.0.3 2018-02-15
|
||||||
|
repmgr: improve switchover handling when "pg_ctl" used to control the
|
||||||
|
server and logging output is not explicitly redirected (Ian)
|
||||||
|
repmgr: improve switchover log messages and exit code when old primary could
|
||||||
|
not be shut down cleanly (Ian)
|
||||||
|
repmgr: check demotion candidate can make a replication connection to the
|
||||||
|
promotion candidate before executing a switchover; GitHub #370 (Ian)
|
||||||
|
repmgr: add check for sufficient walsenders/replication slots before executing
|
||||||
|
a switchover; GitHub #371 (Ian)
|
||||||
|
repmgr: add --dry-run mode to "repmgr standby follow"; GitHub #368 (Ian)
|
||||||
|
repmgr: provide information about the primary node for "standby_register" and
|
||||||
|
"standby_follow" event notifications; GitHub #375 (Ian)
|
||||||
|
repmgr: add "standby_register_sync" event notification; GitHub #374 (Ian)
|
||||||
|
repmgr: output any connection error messages in "cluster show"'s list of
|
||||||
|
warnings; GitHub #369 (Ian)
|
||||||
|
repmgr: ensure an inactive data directory can be deleted; GitHub #366 (Ian)
|
||||||
|
repmgr: fix upstream node display in "repmgr node status"; GitHub #363 (fanf2)
|
||||||
|
repmgr: improve/clarify documentation and update --help output for
|
||||||
|
"primary unregister"; GitHub #373 (Ian)
|
||||||
|
repmgr: allow replication slots when Barman is configured; GitHub #379 (Ian)
|
||||||
|
repmgr: fix parsing of "pg_basebackup_options"; GitHub #376 (Ian)
|
||||||
|
repmgr: ensure "pg_subtrans" directory is created when cloning a standby in
|
||||||
|
Barman mode (Ian)
|
||||||
|
repmgr: fix primary node check in "witness register"; GitHub #377 (Ian)
|
||||||
|
|
||||||
|
4.0.2 2018-01-18
|
||||||
|
repmgr: add missing -W option to getopt_long() invocation; GitHub #350 (Ian)
|
||||||
|
repmgr: automatically create slot name if missing; GitHub #343 (Ian)
|
||||||
|
repmgr: fixes to parsing output of remote repmgr invocations; GitHub #349 (Ian)
|
||||||
|
repmgr: BDR support - create missing connection replication set
|
||||||
|
if required; GitHub #347 (Ian)
|
||||||
|
repmgr: handle missing node record in "repmgr node rejoin"; GitHub #358 (Ian)
|
||||||
|
repmgr: enable documentation to be build as single HTML file; GitHub #353 (fanf2)
|
||||||
|
repmgr: recognize "--terse" option for "repmgr cluster event"; GitHub #360 (Ian)
|
||||||
|
repmgr: add "--wait-start" option for "repmgr standby register"; GitHub #356 (Ian)
|
||||||
|
repmgr: add "%p" event notification parameter for "repmgr standby switchover"
|
||||||
|
containing the node ID of the demoted primary (Ian)
|
||||||
|
docs: various fixes and updates (Ian, Daymel, Martín, ams)
|
||||||
|
|
||||||
|
4.0.1 2017-12-13
|
||||||
|
repmgr: ensure "repmgr node check --action=" returns appropriate return
|
||||||
|
code; GitHub #340 (Ian)
|
||||||
|
repmgr: add missing schema qualification in get_all_node_records_with_upstream()
|
||||||
|
query GitHub #341 (Martín)
|
||||||
|
repmgr: initialise "voting_term" table in application, not extension SQL;
|
||||||
|
GitHub #344 (Ian)
|
||||||
|
repmgr: delete any replication slots copied by pg_rewind; GitHub #334 (Ian)
|
||||||
|
repmgr: fix configuration file sanity check; GitHub #342 (Ian)
|
||||||
|
|
||||||
|
4.0.0 2017-11-21
|
||||||
|
Complete rewrite with many changes; for details see the repmgr 4.0.0 release
|
||||||
|
notes at: https://repmgr.org/docs/4.0/release-4.0.0.html
|
||||||
|
|
||||||
|
3.3.2 2017-06-01
|
||||||
|
Add support for PostgreSQL 10 (Ian)
|
||||||
|
repmgr: ensure --replication-user option is honoured when passing database
|
||||||
|
connection parameters as a conninfo string (Ian)
|
||||||
|
repmgr: improve detection of pg_rewind on remote server (Ian)
|
||||||
|
repmgr: add DETAIL log output for additional clarification of error messages (Ian)
|
||||||
|
repmgr: suppress various spurious error messages in `standby follow` and
|
||||||
|
`standby switchover` (Ian)
|
||||||
|
repmgr: add missing `-P` option (Ian)
|
||||||
|
repmgrd: monitoring statistic reporting fixes (Ian)
|
||||||
|
|
||||||
|
3.3.1 2017-03-13
|
||||||
|
repmgrd: prevent invalid apply lag value being written to the
|
||||||
|
monitoring table (Ian)
|
||||||
|
repmgrd: fix error in XLogRecPtr conversion when calculating
|
||||||
|
monitoring statistics (Ian)
|
||||||
|
repmgr: if replication slots in use, where possible delete slot on old
|
||||||
|
upstream node after following new upstream (Ian)
|
||||||
|
repmgr: improve logging of rsync actions (Ian)
|
||||||
|
repmgr: improve `standby clone` when synchronous replication in use (Ian)
|
||||||
|
repmgr: stricter checking of allowed node id values
|
||||||
|
repmgr: enable `master register --force` when there is a foreign key
|
||||||
|
dependency from a standby node (Ian)
|
||||||
|
|
||||||
|
3.3 2016-12-27
|
||||||
|
repmgr: always log to STDERR even if log facility defined (Ian)
|
||||||
|
repmgr: add --log-to-file to log repmgr output to the defined
|
||||||
|
log facility (Ian)
|
||||||
|
repmgr: improve handling of command line parameter errors (Ian)
|
||||||
|
repmgr: add option --upstream-conninfo to explicitly set
|
||||||
|
'primary_conninfo' in recovery.conf (Ian)
|
||||||
|
repmgr: enable a standby to be registered which isn't running (Ian)
|
||||||
|
repmgr: enable `standby register --force` to update a node record
|
||||||
|
with cascaded downstream node records (Ian)
|
||||||
|
repmgr: add option `--no-conninfo-password` (Abhijit, Ian)
|
||||||
|
repmgr: add initial support for PostgreSQL 10.0 (Ian)
|
||||||
|
repmgr: escape values in primary_conninfo if needed (Ian)
|
||||||
|
|
||||||
|
3.2.1 2016-10-24
|
||||||
|
repmgr: require a valid repmgr cluster name unless -F/--force
|
||||||
|
supplied (Ian)
|
||||||
|
repmgr: check master server is registered with repmgr before
|
||||||
|
cloning (Ian)
|
||||||
|
repmgr: ensure data directory defaults to that of the source node (Ian)
|
||||||
|
repmgr: various fixes to Barman cloning mode (Gianni, Ian)
|
||||||
|
repmgr: fix `repmgr cluster crosscheck` output (Ian)
|
||||||
|
|
||||||
|
3.2 2016-10-05
|
||||||
|
repmgr: add support for cloning from a Barman backup (Gianni)
|
||||||
|
repmgr: add commands `standby matrix` and `standby crosscheck` (Gianni)
|
||||||
|
repmgr: suppress connection error display in `repmgr cluster show`
|
||||||
|
unless `--verbose` supplied (Ian)
|
||||||
|
repmgr: add commands `witness register` and `witness unregister` (Ian)
|
||||||
|
repmgr: enable `standby unregister` / `witness unregister` to be
|
||||||
|
executed for a node which is not running (Ian)
|
||||||
|
repmgr: remove deprecated command line options --initdb-no-pwprompt and
|
||||||
|
-l/--local-port (Ian)
|
||||||
|
repmgr: before cloning with pg_basebackup, check that sufficient free
|
||||||
|
walsenders are available (Ian)
|
||||||
|
repmgr: add option `--wait-sync` for `standby register` which causes
|
||||||
|
repmgr to wait for the registered node record to synchronise to
|
||||||
|
the standby (Ian)
|
||||||
|
repmgr: add option `--copy-external-config-files` for files outside
|
||||||
|
of the data directory (Ian)
|
||||||
|
repmgr: only require `wal_keep_segments` to be set in certain corner
|
||||||
|
cases (Ian)
|
||||||
|
repmgr: better support cloning from a node other than the one to
|
||||||
|
stream from (Ian)
|
||||||
|
repmgrd: add configuration options to override the default pg_ctl
|
||||||
|
commands (Jarkko Oranen, Ian)
|
||||||
|
repmgrd: don't start if node is inactive and failover=automatic (Ian)
|
||||||
|
packaging: improve "repmgr-auto" Debian package (Gianni)
|
||||||
|
|
||||||
|
|
||||||
|
3.1.5 2016-08-15
|
||||||
|
repmgrd: in a failover situation, prevent endless looping when
|
||||||
|
attempting to establish the status of a node with
|
||||||
|
`failover=manual` (Ian)
|
||||||
|
repmgrd: improve handling of failover events on standbys with
|
||||||
|
`failover=manual`, and create a new event notification
|
||||||
|
for this, `standby_disconnect_manual` (Ian)
|
||||||
|
repmgr: add further event notifications (Gianni)
|
||||||
|
repmgr: when executing `standby switchover`, don't collect remote
|
||||||
|
command output unless required (Gianni, Ian)
|
||||||
|
repmgrd: improve standby monitoring query (Ian, based on suggestion
|
||||||
|
from Álvaro)
|
||||||
|
repmgr: various command line handling improvements (Ian)
|
||||||
|
|
||||||
|
3.1.4 2016-07-12
|
||||||
|
repmgr: new configuration option for setting "restore_command"
|
||||||
|
in the recovery.conf file generated by repmgr (Martín)
|
||||||
|
repmgr: add --csv option to "repmgr cluster show" (Gianni)
|
||||||
|
repmgr: enable provision of a conninfo string as the -d/--dbname
|
||||||
|
parameter, similar to other PostgreSQL utilities (Ian)
|
||||||
|
repmgr: during switchover operations improve detection of
|
||||||
|
demotion candidate shutdown (Ian)
|
||||||
|
various bugfixes and documentation updates (Ian, Martín)
|
||||||
|
|
||||||
|
3.1.3 2016-05-17
|
||||||
|
repmgrd: enable monitoring when a standby is catching up by
|
||||||
|
replaying archived WAL (Ian)
|
||||||
|
repmgrd: when upstream_node_id is NULL, assume upstream node
|
||||||
|
to be current master (Ian)
|
||||||
|
repmgrd: check for reappearance of the master node if standby
|
||||||
|
promotion fails (Ian)
|
||||||
|
improve handling of rsync failure conditions (Martín)
|
||||||
|
|
||||||
|
3.1.2 2016-04-12
|
||||||
|
Fix pg_ctl path generation in do_standby_switchover() (Ian)
|
||||||
|
Regularly sync witness server repl_nodes table (Ian)
|
||||||
|
Documentation improvements (Gianni, dhyannataraj)
|
||||||
|
(Experimental) ensure repmgr handles failover slots when copying
|
||||||
|
in rsync mode (Craig, Ian)
|
||||||
|
rsync mode handling fixes (Martín)
|
||||||
|
Enable repmgr to compile against 9.6devel (Ian)
|
||||||
|
|
||||||
|
3.1.1 2016-02-24
|
||||||
|
Add '-P/--pwprompt' option for "repmgr create witness" (Ian)
|
||||||
|
Prevent repmgr/repmgrd running as root (Ian)
|
||||||
|
|
||||||
|
3.1.0 2016-02-01
|
||||||
|
Add "repmgr standby switchover" command (Ian)
|
||||||
|
Revised README file (Ian)
|
||||||
|
Remove requirement for 'archive_mode' to be enabled (Ian)
|
||||||
|
Improve -?/--help output, showing default values if relevant (Ian)
|
||||||
|
Various bugfixes to command line/configuration parameter handling (Ian)
|
||||||
|
|
||||||
|
3.0.3 2016-01-04
|
||||||
|
Create replication slot if required before base backup is run (Abhijit)
|
||||||
|
standy clone: when using rsync, clean up "pg_replslot" directory (Ian)
|
||||||
|
Improve --help output (Ian)
|
||||||
|
Improve config file parsing (Ian)
|
||||||
|
Various logging output improvements, including explicit HINTS (Ian)
|
||||||
|
Add --log-level to explicitly set log level on command line (Ian)
|
||||||
|
Repurpose --verbose to display extra log output (Ian)
|
||||||
|
Add --terse to hide hints and other non-critical output (Ian)
|
||||||
|
Reference internal functions with explicit catalog path (Ian)
|
||||||
|
When following a new primary, have repmgr (not repmgrd) create the new slot (Ian)
|
||||||
|
Add /etc/repmgr.conf as a default configuration file location (Ian)
|
||||||
|
Prevent repmgrd's -v/--verbose option expecting a parameter (Ian)
|
||||||
|
Prevent invalid replication_lag values being written to the monitoring table (Ian)
|
||||||
|
Improve repmgrd behaviour when monitored standby node is temporarily
|
||||||
|
unavailable (Martín)
|
||||||
|
|
||||||
|
3.0.2 2015-10-02
|
||||||
|
Improve handling of --help/--version options; and improve help output (Ian)
|
||||||
|
Improve handling of situation where logfile can't be opened (Ian)
|
||||||
|
Always pass -D/--pgdata option to pg_basebackup (Ian)
|
||||||
|
Bugfix: standby clone --force does not empty pg_xlog (Gianni)
|
||||||
|
Bugfix: autofailover with reconnect_attempts > 1 (Gianni)
|
||||||
|
Bugfix: ignore comments after values (soxwellfb)
|
||||||
|
Bugfix: handle string values in 'node' parameter correctly (Gregory Duchatelet)
|
||||||
|
Allow repmgr to be compiled with a newer libpq (Marco)
|
||||||
|
Bugfix: call update_node_record_set_upstream() for STANDBY FOLLOW (Tomas)
|
||||||
|
Update `repmgr --help` output (per Github report from renard)
|
||||||
|
Update tablespace remapping in --rsync-only mode for 9.5 and later (Ian)
|
||||||
|
Deprecate `-l/--local-port` option - the port can be extracted
|
||||||
|
from the conninfo string in repmgr.conf (Ian)
|
||||||
|
Add STANDBY UNREGISTER (Vik Fearing)
|
||||||
|
Don't fail with error when registering master if schema already defined (Ian)
|
||||||
|
Fixes to whitespace handling when parsing config file (Ian)
|
||||||
|
|
||||||
|
3.0.1 2015-04-16
|
||||||
|
Prevent repmgrd from looping infinitely if node was not registered (Ian)
|
||||||
|
When promoting a standby, have repmgr (not repmgrd) handle metadata updates (Ian)
|
||||||
|
Re-use replication slot if it already exists (Ian)
|
||||||
|
Prevent a test SSH connection being made when not needed (Ian)
|
||||||
|
Correct monitoring table column names (Ian)
|
||||||
|
|
||||||
|
3.0 2015-03-27
|
||||||
|
Require PostgreSQL 9.3 or later (Ian)
|
||||||
|
Use `pg_basebackup` by default (instead of `rsync`) to clone standby servers (Ian)
|
||||||
|
Use `pg_ctl promote` to promote a standby to primary
|
||||||
|
Enable tablespace remapping using `pg_basebackup` (in PostgreSQL 9.3 with `rsync`) (Ian)
|
||||||
|
Support cascaded standbys (Ian)
|
||||||
|
"pg_bindir" no longer required as a configuration parameter (Ian)
|
||||||
|
Enable replication slots to be used (PostgreSQL 9.4 and later (Ian)
|
||||||
|
Command line option "--check-upstream-config" (Ian)
|
||||||
|
Add event logging table and option to execute an external program when an event occurs (Ian)
|
||||||
|
General usability and logging message improvements (Ian)
|
||||||
|
Code consolidation and cleanup (Ian)
|
||||||
|
|
||||||
|
2.0.3 2015-04-16
|
||||||
|
Add -S/--superuser option for witness database creation Ian)
|
||||||
|
Add -c/--fast-checkpoint option for cloning (Christoph)
|
||||||
|
Add option "--initdb-no-pwprompt" (Ian)
|
||||||
|
|
||||||
|
2.0.2 2015-02-17
|
||||||
|
Add "--checksum" in rsync when using "--force" (Jaime)
|
||||||
|
Use createdb/createuser instead of psql (Jaime)
|
||||||
|
Fixes to witness creation and monitoring (wamonite)
|
||||||
|
Use default master port if none supplied (Martín)
|
||||||
|
Documentation fixes and improvements (Ian)
|
||||||
|
|
||||||
|
2.0.1 2014-07-16
|
||||||
|
Documentation fixes and new QUICKSTART file (Ian)
|
||||||
|
Explicitly specify directories to ignore when cloning (Ian)
|
||||||
|
Fix log level for some log messages (Ian)
|
||||||
|
RHEL/CentOS specfile, init script and Makefile fixes (Nathan Van Overloop)
|
||||||
|
Debian init script and config file documentation fixes (József Kószó)
|
||||||
|
Typo fixes (Riegie Godwin Jeyaranchen, PriceChild)
|
||||||
|
|
||||||
|
2.0stable 2014-01-30
|
||||||
|
Documentation fixes (Christian)
|
||||||
|
General refactoring, code quality improvements and stabilization work (Christian)
|
||||||
|
Added proper daemonizing (-d/--daemonize) (Christian)
|
||||||
|
Added PID file handling (-p/--pid-file) (Christian)
|
||||||
|
New config option: monitor_interval_secs (Christian)
|
||||||
|
New config option: retry_promote_interval (Christian)
|
||||||
|
New config option: logfile (Christian)
|
||||||
|
New config option: pg_bindir (Christian)
|
||||||
|
New config option: pgctl_options (Christian)
|
||||||
|
|
||||||
|
2.0beta2 2013-12-19
|
||||||
|
Improve autofailover logic and algorithms (Jaime, Andres)
|
||||||
|
Ignore pg_log when cloning (Jaime)
|
||||||
|
Add timestamps to log line in stderr (Christian)
|
||||||
|
Correctly check wal_keep_segments (Jay Taylor)
|
||||||
|
Add a ssh_options parameter (Jay Taylor)
|
||||||
|
|
||||||
|
2.0beta1 2012-07-27
|
||||||
|
Make CLONE command try to make an exact copy including $PGDATA location (Cedric)
|
||||||
|
Add detection of master failure (Jaime)
|
||||||
|
Add the notion of a witness server (Jaime)
|
||||||
|
Add autofailover capabilities (Jaime)
|
||||||
|
Add a configuration parameter to indicate the script to execute on failover or follow (Jaime)
|
||||||
|
Make the monitoring optional and turned off by default, it can be turned on with --monitoring-history switch (Jaime)
|
||||||
|
Add tunables to specify number of retries to reconnect to master and the time between them (Jaime)
|
||||||
|
|
||||||
|
1.2.0 2012-07-27
|
||||||
|
Test ssh connection before trying to rsync (Cédric)
|
||||||
|
Add CLUSTER SHOW command (Carlo)
|
||||||
|
Add CLUSTER CLEANUP command (Jaime)
|
||||||
|
Add function write_primary_conninfo (Marco)
|
||||||
|
Teach repmgr how to get tablespace's location in different pg version (Jaime)
|
||||||
|
Improve version message (Carlo)
|
||||||
|
|
||||||
|
1.1.1 2012-04-18
|
||||||
|
Add --ignore-rsync-warning (Cédric)
|
||||||
|
Add strnlen for compatibility with OS X (Greg)
|
||||||
|
Improve performance of the repl_status view (Jaime)
|
||||||
|
Remove last argument from log_err (Jaime, Reported by Jeroen Dekkers)
|
||||||
|
Complete documentation about possible error conditions (Jaime)
|
||||||
|
Document how to clean history (Jaime)
|
||||||
|
|
||||||
|
1.1.0 2011-03-09
|
||||||
|
Make options -U, -R and -p not mandatory (Jaime)
|
||||||
|
|
||||||
|
1.1.0b1 2011-02-24
|
||||||
|
Fix missing "--force" option in help (Greg Smith)
|
||||||
|
Correct warning message for wal_keep_segments (Bas van Oostveen)
|
||||||
|
Add Debian build/usage docs (Bas, Hannu Krosing, Cedric Villemain)
|
||||||
|
Add Debian .deb packaging (Hannu)
|
||||||
|
Move configuration data into a structure (Bas, Gabriele Bartolini)
|
||||||
|
Make rsync options configurable (Bas)
|
||||||
|
Add syslog as alternate logging destination (Gabriele)
|
||||||
|
Change from using malloc to static memory allocations (Gabriele)
|
||||||
|
Add debugging messages after every query (Gabriele)
|
||||||
|
Parameterize schema name used for repmgr (Gabriele)
|
||||||
|
Avoid buffer overruns by using snprintf etc. (Gabriele)
|
||||||
|
Fix use of database query after close (Gabriele)
|
||||||
|
Add information about progress during "standby clone" (Gabriele)
|
||||||
|
Fix double free errors in repmgrd (Charles Duffy, Greg)
|
||||||
|
Make repmgr exit with an error code when encountering an error (Charles)
|
||||||
|
Standardize on error return codes, use in repmgrd too (Greg)
|
||||||
|
Add [un]install actions/SQL like most contrib modules (Daniel Farina)
|
||||||
|
Wrap all string construction and produce error on overflow (Daniel)
|
||||||
|
Correct freeing of memory from first_wal_segment (Daniel)
|
||||||
|
Allow creating recovery.conf file with a password (Daniel)
|
||||||
|
Inform when STANDBY CLONE sees an unused config file (Daniel)
|
||||||
|
Use 64-bit computation for WAL apply_lag (Greg)
|
||||||
|
Add info messages for database and general work done (Greg)
|
||||||
|
Map old verbose flag into a useful setting for the new logger (Greg)
|
||||||
|
Document repmgrd startup restrictions and log info about them (Greg)
|
||||||
|
|
||||||
|
1.0.0 2010-12-05
|
||||||
First public release
|
First public release
|
||||||
|
|||||||
52
Makefile.in
52
Makefile.in
@@ -11,7 +11,13 @@ EXTENSION = repmgr
|
|||||||
|
|
||||||
DATA = \
|
DATA = \
|
||||||
repmgr--unpackaged--4.0.sql \
|
repmgr--unpackaged--4.0.sql \
|
||||||
repmgr--4.0.sql
|
repmgr--4.0.sql \
|
||||||
|
repmgr--4.0--4.1.sql \
|
||||||
|
repmgr--4.1.sql \
|
||||||
|
repmgr--4.1--4.2.sql \
|
||||||
|
repmgr--4.2.sql \
|
||||||
|
repmgr--4.2--4.3.sql \
|
||||||
|
repmgr--4.3.sql
|
||||||
|
|
||||||
REGRESS = repmgr_extension
|
REGRESS = repmgr_extension
|
||||||
|
|
||||||
@@ -26,20 +32,26 @@ all: \
|
|||||||
PG_CPPFLAGS = -std=gnu89 -I$(includedir_internal) -I$(libpq_srcdir) -Wall -Wmissing-prototypes -Wmissing-declarations $(EXTRA_CFLAGS)
|
PG_CPPFLAGS = -std=gnu89 -I$(includedir_internal) -I$(libpq_srcdir) -Wall -Wmissing-prototypes -Wmissing-declarations $(EXTRA_CFLAGS)
|
||||||
SHLIB_LINK = $(libpq)
|
SHLIB_LINK = $(libpq)
|
||||||
|
|
||||||
HEADERS = $(wildcard *.h)
|
|
||||||
|
|
||||||
OBJS = \
|
OBJS = \
|
||||||
repmgr.o
|
repmgr.o
|
||||||
|
|
||||||
include Makefile.global
|
include Makefile.global
|
||||||
|
|
||||||
|
ifeq ($(vpath_build),yes)
|
||||||
|
HEADERS = $(wildcard *.h)
|
||||||
|
else
|
||||||
|
HEADERS_built = $(wildcard *.h)
|
||||||
|
endif
|
||||||
|
|
||||||
$(info Building against PostgreSQL $(MAJORVERSION))
|
$(info Building against PostgreSQL $(MAJORVERSION))
|
||||||
|
|
||||||
REPMGR_CLIENT_OBJS = repmgr-client.o \
|
REPMGR_CLIENT_OBJS = repmgr-client.o \
|
||||||
repmgr-action-primary.o repmgr-action-standby.o repmgr-action-bdr.o repmgr-action-cluster.o repmgr-action-node.o \
|
repmgr-action-primary.o repmgr-action-standby.o repmgr-action-witness.o \
|
||||||
configfile.o log.o strutil.o controldata.o dirutil.o compat.o dbutils.o
|
repmgr-action-bdr.o repmgr-action-cluster.o repmgr-action-node.o repmgr-action-daemon.o \
|
||||||
REPMGRD_OBJS = repmgrd.o repmgrd-physical.o repmgrd-bdr.o configfile.o log.o dbutils.o strutil.o controldata.o
|
configfile.o log.o strutil.o controldata.o dirutil.o compat.o dbutils.o sysutils.o
|
||||||
|
REPMGRD_OBJS = repmgrd.o repmgrd-physical.o repmgrd-bdr.o configfile.o log.o dbutils.o strutil.o controldata.o compat.o sysutils.o
|
||||||
DATE=$(shell date "+%Y-%m-%d")
|
DATE=$(shell date "+%Y-%m-%d")
|
||||||
|
|
||||||
repmgr_version.h: repmgr_version.h.in
|
repmgr_version.h: repmgr_version.h.in
|
||||||
@@ -63,32 +75,26 @@ 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
|
||||||
|
|
||||||
additional-clean:
|
additional-clean:
|
||||||
rm -f repmgr-client.o
|
rm -f *.o
|
||||||
rm -f repmgr-action-primary.o
|
|
||||||
rm -f repmgr-action-standby.o
|
|
||||||
rm -f repmgr-action-bdr.o
|
|
||||||
rm -f repmgr-action-node.o
|
|
||||||
rm -f repmgr-action-cluster.o
|
|
||||||
rm -f repmgrd.o
|
|
||||||
rm -f repmgrd-physical.o
|
|
||||||
rm -f repmgrd-bdr.o
|
|
||||||
rm -f compat.o
|
|
||||||
rm -f configfile.o
|
|
||||||
rm -f controldata.o
|
|
||||||
rm -f dbutils.o
|
|
||||||
rm -f dirutil.o
|
|
||||||
rm -f log.o
|
|
||||||
rm -f strutil.o
|
|
||||||
|
|
||||||
maintainer-additional-clean: clean
|
additional-maintainer-clean: clean
|
||||||
rm -f configure
|
$(MAKE) -C doc maintainer-clean
|
||||||
rm -f config.status config.log
|
rm -f config.status config.log
|
||||||
|
rm -f config.h
|
||||||
|
rm -f repmgr_version.h
|
||||||
rm -f Makefile
|
rm -f Makefile
|
||||||
|
rm -f Makefile.global
|
||||||
@rm -rf autom4te.cache/
|
@rm -rf autom4te.cache/
|
||||||
|
|
||||||
ifeq ($(MAJORVERSION),$(filter $(MAJORVERSION),9.3 9.4))
|
ifeq ($(MAJORVERSION),$(filter $(MAJORVERSION),9.3 9.4))
|
||||||
|
|||||||
20
TODO.md
Normal file
20
TODO.md
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
TODO
|
||||||
|
====
|
||||||
|
|
||||||
|
This file contains a list of improvements which are desireable and/or have
|
||||||
|
been requested, and which we aim to address/implement when time and resources
|
||||||
|
permit.
|
||||||
|
|
||||||
|
It is *not* a roadmap and there's no guarantee of any item being implemented
|
||||||
|
within any given timeframe.
|
||||||
|
|
||||||
|
|
||||||
|
Enable suspension of repmgrd failover
|
||||||
|
-------------------------------------
|
||||||
|
|
||||||
|
When performing maintenance, e.g. a switchover, it's necessary to stop all
|
||||||
|
repmgrd nodes to prevent unintended failover; this is obviously inconvenient.
|
||||||
|
We'll need to implement some way of notifying each repmgrd to suspend automatic
|
||||||
|
failover until further notice.
|
||||||
|
|
||||||
|
Requested in GitHub #410 ( https://github.com/2ndQuadrant/repmgr/issues/410 )
|
||||||
35
compat.c
35
compat.c
@@ -6,7 +6,7 @@
|
|||||||
* supported PostgreSQL versions. They're unlikely to change but
|
* supported PostgreSQL versions. They're unlikely to change but
|
||||||
* it would be worth keeping an eye on them for any fixes/improvements.
|
* it would be worth keeping an eye on them for any fixes/improvements.
|
||||||
*
|
*
|
||||||
* Copyright (c) 2ndQuadrant, 2010-2017
|
* Copyright (c) 2ndQuadrant, 2010-2019
|
||||||
*
|
*
|
||||||
* Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
@@ -98,9 +98,42 @@ appendShellString(PQExpBuffer buf, const char *str)
|
|||||||
|
|
||||||
if (*p == '\'')
|
if (*p == '\'')
|
||||||
appendPQExpBufferStr(buf, "'\"'\"'");
|
appendPQExpBufferStr(buf, "'\"'\"'");
|
||||||
|
else if (*p == '&')
|
||||||
|
appendPQExpBufferStr(buf, "\\&");
|
||||||
else
|
else
|
||||||
appendPQExpBufferChar(buf, *p);
|
appendPQExpBufferChar(buf, *p);
|
||||||
}
|
}
|
||||||
|
|
||||||
appendPQExpBufferChar(buf, '\'');
|
appendPQExpBufferChar(buf, '\'');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Adapted from: src/fe_utils/string_utils.c
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
appendRemoteShellString(PQExpBuffer buf, const char *str)
|
||||||
|
{
|
||||||
|
const char *p;
|
||||||
|
|
||||||
|
appendPQExpBufferStr(buf, "\\'");
|
||||||
|
|
||||||
|
for (p = str; *p; p++)
|
||||||
|
{
|
||||||
|
if (*p == '\n' || *p == '\r')
|
||||||
|
{
|
||||||
|
fprintf(stderr,
|
||||||
|
_("shell command argument contains a newline or carriage return: \"%s\"\n"),
|
||||||
|
str);
|
||||||
|
exit(ERR_BAD_CONFIG);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*p == '\'')
|
||||||
|
appendPQExpBufferStr(buf, "'\"'\"'");
|
||||||
|
else if (*p == '&')
|
||||||
|
appendPQExpBufferStr(buf, "\\&");
|
||||||
|
else
|
||||||
|
appendPQExpBufferChar(buf, *p);
|
||||||
|
}
|
||||||
|
|
||||||
|
appendPQExpBufferStr(buf, "\\'");
|
||||||
|
}
|
||||||
|
|||||||
4
compat.h
4
compat.h
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* compat.h
|
* compat.h
|
||||||
* Copyright (c) 2ndQuadrant, 2010-2017
|
* Copyright (c) 2ndQuadrant, 2010-2019
|
||||||
*
|
*
|
||||||
* Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
@@ -27,4 +27,6 @@ extern void appendConnStrVal(PQExpBuffer buf, const char *str);
|
|||||||
|
|
||||||
extern void appendShellString(PQExpBuffer buf, const char *str);
|
extern void appendShellString(PQExpBuffer buf, const char *str);
|
||||||
|
|
||||||
|
extern void appendRemoteShellString(PQExpBuffer buf, const char *str);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,4 +1,2 @@
|
|||||||
/* config.h.in. Generated from configure.in by autoheader. */
|
/* config.h.in. Generated from configure.in by autoheader. */
|
||||||
|
|
||||||
/* Only build repmgr for BDR */
|
|
||||||
#undef BDR_ONLY
|
|
||||||
|
|||||||
640
configfile.c
640
configfile.c
File diff suppressed because it is too large
Load Diff
106
configfile.h
106
configfile.h
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* configfile.h
|
* configfile.h
|
||||||
*
|
*
|
||||||
* Copyright (c) 2ndQuadrant, 2010-2017
|
* Copyright (c) 2ndQuadrant, 2010-2019
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
@@ -37,6 +37,13 @@ typedef enum
|
|||||||
FAILOVER_AUTOMATIC
|
FAILOVER_AUTOMATIC
|
||||||
} failover_mode_opt;
|
} failover_mode_opt;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
CHECK_PING,
|
||||||
|
CHECK_QUERY,
|
||||||
|
CHECK_CONNECTION
|
||||||
|
} ConnectionCheckType;
|
||||||
|
|
||||||
typedef struct EventNotificationListCell
|
typedef struct EventNotificationListCell
|
||||||
{
|
{
|
||||||
struct EventNotificationListCell *next;
|
struct EventNotificationListCell *next;
|
||||||
@@ -69,11 +76,13 @@ typedef struct
|
|||||||
{
|
{
|
||||||
/* node information */
|
/* node information */
|
||||||
int node_id;
|
int node_id;
|
||||||
char node_name[MAXLEN];
|
char node_name[NAMEDATALEN];
|
||||||
char conninfo[MAXLEN];
|
char conninfo[MAXLEN];
|
||||||
char replication_user[NAMEDATALEN];
|
char replication_user[NAMEDATALEN];
|
||||||
char data_directory[MAXPGPATH];
|
char data_directory[MAXPGPATH];
|
||||||
|
char config_directory[MAXPGPATH];
|
||||||
char pg_bindir[MAXPGPATH];
|
char pg_bindir[MAXPGPATH];
|
||||||
|
char repmgr_bindir[MAXPGPATH];
|
||||||
int replication_type;
|
int replication_type;
|
||||||
|
|
||||||
/* log settings */
|
/* log settings */
|
||||||
@@ -82,14 +91,32 @@ typedef struct
|
|||||||
char log_file[MAXLEN];
|
char log_file[MAXLEN];
|
||||||
int log_status_interval;
|
int log_status_interval;
|
||||||
|
|
||||||
/* standby action settings */
|
/* standby clone settings */
|
||||||
bool use_replication_slots;
|
bool use_replication_slots;
|
||||||
char pg_basebackup_options[MAXLEN];
|
char pg_basebackup_options[MAXLEN];
|
||||||
char restore_command[MAXLEN];
|
char restore_command[MAXLEN];
|
||||||
TablespaceList tablespace_mapping;
|
TablespaceList tablespace_mapping;
|
||||||
char recovery_min_apply_delay[MAXLEN];
|
char recovery_min_apply_delay[MAXLEN];
|
||||||
bool recovery_min_apply_delay_provided;
|
bool recovery_min_apply_delay_provided;
|
||||||
|
char archive_cleanup_command[MAXLEN];
|
||||||
bool use_primary_conninfo_password;
|
bool use_primary_conninfo_password;
|
||||||
|
char passfile[MAXPGPATH];
|
||||||
|
|
||||||
|
/* standby promote settings */
|
||||||
|
int promote_check_timeout;
|
||||||
|
int promote_check_interval;
|
||||||
|
|
||||||
|
/* standby follow settings */
|
||||||
|
int primary_follow_timeout;
|
||||||
|
int standby_follow_timeout;
|
||||||
|
|
||||||
|
/* standby switchover settings */
|
||||||
|
int shutdown_check_timeout;
|
||||||
|
int standby_reconnect_timeout;
|
||||||
|
int wal_receive_check_timeout;
|
||||||
|
|
||||||
|
/* node rejoin settings */
|
||||||
|
int node_rejoin_timeout;
|
||||||
|
|
||||||
/* node check settings */
|
/* node check settings */
|
||||||
int archive_ready_warning;
|
int archive_ready_warning;
|
||||||
@@ -97,6 +124,9 @@ typedef struct
|
|||||||
int replication_lag_warning;
|
int replication_lag_warning;
|
||||||
int replication_lag_critical;
|
int replication_lag_critical;
|
||||||
|
|
||||||
|
/* witness settings */
|
||||||
|
int witness_sync_interval;
|
||||||
|
|
||||||
/* repmgrd settings */
|
/* repmgrd settings */
|
||||||
failover_mode_opt failover;
|
failover_mode_opt failover;
|
||||||
char location[MAXLEN];
|
char location[MAXLEN];
|
||||||
@@ -110,7 +140,14 @@ typedef struct
|
|||||||
int degraded_monitoring_timeout;
|
int degraded_monitoring_timeout;
|
||||||
int async_query_timeout;
|
int async_query_timeout;
|
||||||
int primary_notification_timeout;
|
int primary_notification_timeout;
|
||||||
int primary_follow_timeout;
|
int repmgrd_standby_startup_timeout;
|
||||||
|
char repmgrd_pid_file[MAXPGPATH];
|
||||||
|
bool standby_disconnect_on_failover;
|
||||||
|
int sibling_nodes_disconnect_timeout;
|
||||||
|
ConnectionCheckType connection_check_type;
|
||||||
|
bool primary_visibility_consensus;
|
||||||
|
char failover_validation_command[MAXPGPATH];
|
||||||
|
int election_rerun_interval;
|
||||||
|
|
||||||
/* BDR settings */
|
/* BDR settings */
|
||||||
bool bdr_local_monitoring_only;
|
bool bdr_local_monitoring_only;
|
||||||
@@ -118,14 +155,18 @@ typedef struct
|
|||||||
|
|
||||||
/* service settings */
|
/* service settings */
|
||||||
char pg_ctl_options[MAXLEN];
|
char pg_ctl_options[MAXLEN];
|
||||||
char service_stop_command[MAXLEN];
|
char service_start_command[MAXPGPATH];
|
||||||
char service_start_command[MAXLEN];
|
char service_stop_command[MAXPGPATH];
|
||||||
char service_restart_command[MAXLEN];
|
char service_restart_command[MAXPGPATH];
|
||||||
char service_reload_command[MAXLEN];
|
char service_reload_command[MAXPGPATH];
|
||||||
char service_promote_command[MAXLEN];
|
char service_promote_command[MAXPGPATH];
|
||||||
|
|
||||||
|
/* repmgrd service settings */
|
||||||
|
char repmgrd_service_start_command[MAXPGPATH];
|
||||||
|
char repmgrd_service_stop_command[MAXPGPATH];
|
||||||
|
|
||||||
/* event notification settings */
|
/* event notification settings */
|
||||||
char event_notification_command[MAXLEN];
|
char event_notification_command[MAXPGPATH];
|
||||||
char event_notifications_orig[MAXLEN];
|
char event_notifications_orig[MAXLEN];
|
||||||
EventNotificationList event_notifications;
|
EventNotificationList event_notifications;
|
||||||
|
|
||||||
@@ -149,14 +190,27 @@ typedef struct
|
|||||||
|
|
||||||
#define T_CONFIGURATION_OPTIONS_INITIALIZER { \
|
#define T_CONFIGURATION_OPTIONS_INITIALIZER { \
|
||||||
/* node information */ \
|
/* node information */ \
|
||||||
UNKNOWN_NODE_ID, "", "", "", "", "", REPLICATION_TYPE_PHYSICAL, \
|
UNKNOWN_NODE_ID, "", "", "", "", "", "", "", REPLICATION_TYPE_PHYSICAL, \
|
||||||
/* log settings */ \
|
/* log settings */ \
|
||||||
"", "", "", DEFAULT_LOG_STATUS_INTERVAL, \
|
"", "", "", DEFAULT_LOG_STATUS_INTERVAL, \
|
||||||
/* standby action settings */ \
|
/* standby clone settings */ \
|
||||||
false, "", "", { NULL, NULL }, "", false, false, \
|
false, "", "", { NULL, NULL }, "", false, "", false, "", \
|
||||||
|
/* standby promote settings */ \
|
||||||
|
DEFAULT_PROMOTE_CHECK_TIMEOUT, DEFAULT_PROMOTE_CHECK_INTERVAL, \
|
||||||
|
/* standby follow settings */ \
|
||||||
|
DEFAULT_PRIMARY_FOLLOW_TIMEOUT, \
|
||||||
|
DEFAULT_STANDBY_FOLLOW_TIMEOUT, \
|
||||||
|
/* standby switchover settings */ \
|
||||||
|
DEFAULT_SHUTDOWN_CHECK_TIMEOUT, \
|
||||||
|
DEFAULT_STANDBY_RECONNECT_TIMEOUT, \
|
||||||
|
DEFAULT_WAL_RECEIVE_CHECK_TIMEOUT, \
|
||||||
|
/* node rejoin settings */ \
|
||||||
|
DEFAULT_NODE_REJOIN_TIMEOUT, \
|
||||||
/* node check settings */ \
|
/* node check settings */ \
|
||||||
DEFAULT_ARCHIVE_READY_WARNING, DEFAULT_ARCHIVE_READY_CRITICAL, \
|
DEFAULT_ARCHIVE_READY_WARNING, DEFAULT_ARCHIVE_READY_CRITICAL, \
|
||||||
DEFAULT_REPLICATION_LAG_WARNING, DEFAULT_REPLICATION_LAG_CRITICAL, \
|
DEFAULT_REPLICATION_LAG_WARNING, DEFAULT_REPLICATION_LAG_CRITICAL, \
|
||||||
|
/* witness settings */ \
|
||||||
|
DEFAULT_WITNESS_SYNC_INTERVAL, \
|
||||||
/* repmgrd settings */ \
|
/* repmgrd settings */ \
|
||||||
FAILOVER_MANUAL, DEFAULT_LOCATION, DEFAULT_PRIORITY, "", "", \
|
FAILOVER_MANUAL, DEFAULT_LOCATION, DEFAULT_PRIORITY, "", "", \
|
||||||
DEFAULT_MONITORING_INTERVAL, \
|
DEFAULT_MONITORING_INTERVAL, \
|
||||||
@@ -164,12 +218,15 @@ typedef struct
|
|||||||
DEFAULT_RECONNECTION_INTERVAL, \
|
DEFAULT_RECONNECTION_INTERVAL, \
|
||||||
false, -1, \
|
false, -1, \
|
||||||
DEFAULT_ASYNC_QUERY_TIMEOUT, \
|
DEFAULT_ASYNC_QUERY_TIMEOUT, \
|
||||||
DEFAULT_PRIMARY_NOTIFICATION_TIMEOUT, \
|
DEFAULT_PRIMARY_NOTIFICATION_TIMEOUT, \
|
||||||
DEFAULT_PRIMARY_FOLLOW_TIMEOUT, \
|
-1, "", false, DEFAULT_SIBLING_NODES_DISCONNECT_TIMEOUT, \
|
||||||
|
CHECK_PING, true, "", DEFAULT_ELECTION_RERUN_INTERVAL, \
|
||||||
/* BDR settings */ \
|
/* BDR settings */ \
|
||||||
false, DEFAULT_BDR_RECOVERY_TIMEOUT, \
|
false, DEFAULT_BDR_RECOVERY_TIMEOUT, \
|
||||||
/* service settings */ \
|
/* service settings */ \
|
||||||
"", "", "", "", "", "", \
|
"", "", "", "", "", "", \
|
||||||
|
/* repmgrd service settings */ \
|
||||||
|
"", "", \
|
||||||
/* event notification settings */ \
|
/* event notification settings */ \
|
||||||
"", "", { NULL, NULL }, \
|
"", "", { NULL, NULL }, \
|
||||||
/* barman settings */ \
|
/* barman settings */ \
|
||||||
@@ -241,30 +298,37 @@ typedef struct
|
|||||||
"", "", "", "" \
|
"", "", "", "" \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include "dbutils.h"
|
||||||
|
|
||||||
void set_progname(const char *argv0);
|
void set_progname(const char *argv0);
|
||||||
const char *progname(void);
|
const char *progname(void);
|
||||||
|
|
||||||
void load_config(const char *config_file, bool verbose, bool terse, t_configuration_options *options, char *argv0);
|
void load_config(const char *config_file, bool verbose, bool terse, t_configuration_options *options, char *argv0);
|
||||||
void parse_config(t_configuration_options *options, bool terse);
|
bool reload_config(t_configuration_options *orig_options, t_server_type server_type);
|
||||||
bool reload_config(t_configuration_options *orig_options);
|
|
||||||
|
|
||||||
bool parse_recovery_conf(const char *data_dir, t_recovery_conf *conf);
|
bool parse_recovery_conf(const char *data_dir, t_recovery_conf *conf);
|
||||||
|
|
||||||
|
bool parse_bool(const char *s,
|
||||||
|
const char *config_item,
|
||||||
|
ItemList *error_list);
|
||||||
|
|
||||||
int repmgr_atoi(const char *s,
|
int repmgr_atoi(const char *s,
|
||||||
const char *config_item,
|
const char *config_item,
|
||||||
ItemList *error_list,
|
ItemList *error_list,
|
||||||
int minval);
|
int minval);
|
||||||
|
|
||||||
|
|
||||||
bool parse_pg_basebackup_options(const char *pg_basebackup_options,
|
bool parse_pg_basebackup_options(const char *pg_basebackup_options,
|
||||||
t_basebackup_options *backup_options,
|
t_basebackup_options *backup_options,
|
||||||
int server_version_num,
|
int server_version_num,
|
||||||
ItemList *error_list);
|
ItemList *error_list);
|
||||||
|
|
||||||
|
int parse_output_to_argv(const char *string, char ***argv_array);
|
||||||
|
void free_parsed_argv(char ***argv_array);
|
||||||
|
|
||||||
|
|
||||||
/* called by repmgr-client and repmgrd */
|
/* called by repmgr-client and repmgrd */
|
||||||
void exit_with_cli_errors(ItemList *error_list);
|
void exit_with_cli_errors(ItemList *error_list, const char *repmgr_command);
|
||||||
void print_item_list(ItemList *item_list);
|
void print_item_list(ItemList *item_list);
|
||||||
|
const char *print_connection_check_type(ConnectionCheckType type);
|
||||||
|
|
||||||
#endif /* _REPMGR_CONFIGFILE_H_ */
|
#endif /* _REPMGR_CONFIGFILE_H_ */
|
||||||
|
|||||||
61
configure
vendored
61
configure
vendored
@@ -1,8 +1,8 @@
|
|||||||
#! /bin/sh
|
#! /bin/sh
|
||||||
# Guess values for system-dependent variables and create Makefiles.
|
# Guess values for system-dependent variables and create Makefiles.
|
||||||
# Generated by GNU Autoconf 2.69 for repmgr 4.0.
|
# Generated by GNU Autoconf 2.69 for repmgr 4.3.
|
||||||
#
|
#
|
||||||
# Report bugs to <pgsql-bugs@postgresql.org>.
|
# Report bugs to <repmgr@googlegroups.com>.
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
|
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
|
||||||
@@ -11,7 +11,7 @@
|
|||||||
# This configure script is free software; the Free Software Foundation
|
# This configure script is free software; the Free Software Foundation
|
||||||
# gives unlimited permission to copy, distribute and modify it.
|
# gives unlimited permission to copy, distribute and modify it.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2010-2017, 2ndQuadrant Ltd.
|
# Copyright (c) 2010-2019, 2ndQuadrant Ltd.
|
||||||
## -------------------- ##
|
## -------------------- ##
|
||||||
## M4sh Initialization. ##
|
## M4sh Initialization. ##
|
||||||
## -------------------- ##
|
## -------------------- ##
|
||||||
@@ -269,7 +269,7 @@ fi
|
|||||||
$as_echo "$0: be upgraded to zsh 4.3.4 or later."
|
$as_echo "$0: be upgraded to zsh 4.3.4 or later."
|
||||||
else
|
else
|
||||||
$as_echo "$0: Please tell bug-autoconf@gnu.org and
|
$as_echo "$0: Please tell bug-autoconf@gnu.org and
|
||||||
$0: pgsql-bugs@postgresql.org about your system, including
|
$0: repmgr@googlegroups.com about your system, including
|
||||||
$0: any error possibly output before this message. Then
|
$0: any error possibly output before this message. Then
|
||||||
$0: install a modern shell, or manually run the script
|
$0: install a modern shell, or manually run the script
|
||||||
$0: under such a shell if you do have one."
|
$0: under such a shell if you do have one."
|
||||||
@@ -582,10 +582,10 @@ MAKEFLAGS=
|
|||||||
# Identity of this package.
|
# Identity of this package.
|
||||||
PACKAGE_NAME='repmgr'
|
PACKAGE_NAME='repmgr'
|
||||||
PACKAGE_TARNAME='repmgr'
|
PACKAGE_TARNAME='repmgr'
|
||||||
PACKAGE_VERSION='4.0'
|
PACKAGE_VERSION='4.3'
|
||||||
PACKAGE_STRING='repmgr 4.0'
|
PACKAGE_STRING='repmgr 4.3'
|
||||||
PACKAGE_BUGREPORT='pgsql-bugs@postgresql.org'
|
PACKAGE_BUGREPORT='repmgr@googlegroups.com'
|
||||||
PACKAGE_URL='https://2ndquadrant.com/en/resources/repmgr/'
|
PACKAGE_URL='https://repmgr.org/'
|
||||||
|
|
||||||
ac_subst_vars='LTLIBOBJS
|
ac_subst_vars='LTLIBOBJS
|
||||||
LIBOBJS
|
LIBOBJS
|
||||||
@@ -633,7 +633,6 @@ SHELL'
|
|||||||
ac_subst_files=''
|
ac_subst_files=''
|
||||||
ac_user_opts='
|
ac_user_opts='
|
||||||
enable_option_checking
|
enable_option_checking
|
||||||
with_bdr_only
|
|
||||||
'
|
'
|
||||||
ac_precious_vars='build_alias
|
ac_precious_vars='build_alias
|
||||||
host_alias
|
host_alias
|
||||||
@@ -1179,7 +1178,7 @@ if test "$ac_init_help" = "long"; then
|
|||||||
# Omit some internal or obsolete options to make the list less imposing.
|
# Omit some internal or obsolete options to make the list less imposing.
|
||||||
# This message is too long to be a string in the A/UX 3.1 sh.
|
# This message is too long to be a string in the A/UX 3.1 sh.
|
||||||
cat <<_ACEOF
|
cat <<_ACEOF
|
||||||
\`configure' configures repmgr 4.0 to adapt to many kinds of systems.
|
\`configure' configures repmgr 4.3 to adapt to many kinds of systems.
|
||||||
|
|
||||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||||
|
|
||||||
@@ -1240,23 +1239,18 @@ fi
|
|||||||
|
|
||||||
if test -n "$ac_init_help"; then
|
if test -n "$ac_init_help"; then
|
||||||
case $ac_init_help in
|
case $ac_init_help in
|
||||||
short | recursive ) echo "Configuration of repmgr 4.0:";;
|
short | recursive ) echo "Configuration of repmgr 4.3:";;
|
||||||
esac
|
esac
|
||||||
cat <<\_ACEOF
|
cat <<\_ACEOF
|
||||||
|
|
||||||
Optional Packages:
|
|
||||||
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
|
|
||||||
--without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
|
|
||||||
--with-bdr-only BDR-only build
|
|
||||||
|
|
||||||
Some influential environment variables:
|
Some influential environment variables:
|
||||||
PG_CONFIG Location to find pg_config for target PostgreSQL (default PATH)
|
PG_CONFIG Location to find pg_config for target PostgreSQL (default PATH)
|
||||||
|
|
||||||
Use these variables to override the choices made by `configure' or to help
|
Use these variables to override the choices made by `configure' or to help
|
||||||
it to find libraries and programs with nonstandard names/locations.
|
it to find libraries and programs with nonstandard names/locations.
|
||||||
|
|
||||||
Report bugs to <pgsql-bugs@postgresql.org>.
|
Report bugs to <repmgr@googlegroups.com>.
|
||||||
repmgr home page: <https://2ndquadrant.com/en/resources/repmgr/>.
|
repmgr home page: <https://repmgr.org/>.
|
||||||
_ACEOF
|
_ACEOF
|
||||||
ac_status=$?
|
ac_status=$?
|
||||||
fi
|
fi
|
||||||
@@ -1319,14 +1313,14 @@ fi
|
|||||||
test -n "$ac_init_help" && exit $ac_status
|
test -n "$ac_init_help" && exit $ac_status
|
||||||
if $ac_init_version; then
|
if $ac_init_version; then
|
||||||
cat <<\_ACEOF
|
cat <<\_ACEOF
|
||||||
repmgr configure 4.0
|
repmgr configure 4.3
|
||||||
generated by GNU Autoconf 2.69
|
generated by GNU Autoconf 2.69
|
||||||
|
|
||||||
Copyright (C) 2012 Free Software Foundation, Inc.
|
Copyright (C) 2012 Free Software Foundation, Inc.
|
||||||
This configure script is free software; the Free Software Foundation
|
This configure script is free software; the Free Software Foundation
|
||||||
gives unlimited permission to copy, distribute and modify it.
|
gives unlimited permission to copy, distribute and modify it.
|
||||||
|
|
||||||
Copyright (c) 2010-2017, 2ndQuadrant Ltd.
|
Copyright (c) 2010-2019, 2ndQuadrant Ltd.
|
||||||
_ACEOF
|
_ACEOF
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
@@ -1338,7 +1332,7 @@ cat >config.log <<_ACEOF
|
|||||||
This file contains any messages produced by compilers while
|
This file contains any messages produced by compilers while
|
||||||
running configure, to aid debugging if configure makes a mistake.
|
running configure, to aid debugging if configure makes a mistake.
|
||||||
|
|
||||||
It was created by repmgr $as_me 4.0, which was
|
It was created by repmgr $as_me 4.3, which was
|
||||||
generated by GNU Autoconf 2.69. Invocation command line was
|
generated by GNU Autoconf 2.69. Invocation command line was
|
||||||
|
|
||||||
$ $0 $@
|
$ $0 $@
|
||||||
@@ -1694,20 +1688,6 @@ ac_config_headers="$ac_config_headers config.h"
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Check whether --with-bdr_only was given.
|
|
||||||
if test "${with_bdr_only+set}" = set; then :
|
|
||||||
withval=$with_bdr_only;
|
|
||||||
fi
|
|
||||||
|
|
||||||
if test "x$with_bdr_only" != "x"; then :
|
|
||||||
|
|
||||||
$as_echo "#define BDR_ONLY \"1\"" >>confdefs.h
|
|
||||||
|
|
||||||
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
|
||||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5
|
||||||
$as_echo_n "checking for a sed that does not truncate output... " >&6; }
|
$as_echo_n "checking for a sed that does not truncate output... " >&6; }
|
||||||
if ${ac_cv_path_SED+:} false; then :
|
if ${ac_cv_path_SED+:} false; then :
|
||||||
@@ -1871,6 +1851,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
|
||||||
@@ -2377,7 +2359,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
|
|||||||
# report actual input values of CONFIG_FILES etc. instead of their
|
# report actual input values of CONFIG_FILES etc. instead of their
|
||||||
# values after options handling.
|
# values after options handling.
|
||||||
ac_log="
|
ac_log="
|
||||||
This file was extended by repmgr $as_me 4.0, which was
|
This file was extended by repmgr $as_me 4.3, which was
|
||||||
generated by GNU Autoconf 2.69. Invocation command line was
|
generated by GNU Autoconf 2.69. Invocation command line was
|
||||||
|
|
||||||
CONFIG_FILES = $CONFIG_FILES
|
CONFIG_FILES = $CONFIG_FILES
|
||||||
@@ -2433,14 +2415,14 @@ $config_files
|
|||||||
Configuration headers:
|
Configuration headers:
|
||||||
$config_headers
|
$config_headers
|
||||||
|
|
||||||
Report bugs to <pgsql-bugs@postgresql.org>.
|
Report bugs to <repmgr@googlegroups.com>.
|
||||||
repmgr home page: <https://2ndquadrant.com/en/resources/repmgr/>."
|
repmgr home page: <https://repmgr.org/>."
|
||||||
|
|
||||||
_ACEOF
|
_ACEOF
|
||||||
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
||||||
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
|
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
|
||||||
ac_cs_version="\\
|
ac_cs_version="\\
|
||||||
repmgr config.status 4.0
|
repmgr config.status 4.3
|
||||||
configured by $0, generated by GNU Autoconf 2.69,
|
configured by $0, generated by GNU Autoconf 2.69,
|
||||||
with options \\"\$ac_cs_config\\"
|
with options \\"\$ac_cs_config\\"
|
||||||
|
|
||||||
@@ -2564,6 +2546,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
|
||||||
|
|||||||
11
configure.in
11
configure.in
@@ -1,17 +1,11 @@
|
|||||||
AC_INIT([repmgr], [4.0], [pgsql-bugs@postgresql.org], [repmgr], [https://2ndquadrant.com/en/resources/repmgr/])
|
AC_INIT([repmgr], [4.3], [repmgr@googlegroups.com], [repmgr], [https://repmgr.org/])
|
||||||
|
|
||||||
AC_COPYRIGHT([Copyright (c) 2010-2017, 2ndQuadrant Ltd.])
|
AC_COPYRIGHT([Copyright (c) 2010-2019, 2ndQuadrant Ltd.])
|
||||||
|
|
||||||
AC_CONFIG_HEADER(config.h)
|
AC_CONFIG_HEADER(config.h)
|
||||||
|
|
||||||
AC_ARG_VAR([PG_CONFIG], [Location to find pg_config for target PostgreSQL (default PATH)])
|
AC_ARG_VAR([PG_CONFIG], [Location to find pg_config for target PostgreSQL (default PATH)])
|
||||||
|
|
||||||
AC_ARG_WITH([bdr_only], [AS_HELP_STRING([--with-bdr-only], [BDR-only build])])
|
|
||||||
AS_IF([test "x$with_bdr_only" != "x"],
|
|
||||||
[AC_DEFINE([BDR_ONLY], ["1"], [Only build repmgr for BDR])]
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
AC_PROG_SED
|
AC_PROG_SED
|
||||||
|
|
||||||
if test -z "$PG_CONFIG"; then
|
if test -z "$PG_CONFIG"; then
|
||||||
@@ -65,5 +59,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
|
||||||
|
|
||||||
|
|||||||
262
controldata.c
262
controldata.c
@@ -1,6 +1,12 @@
|
|||||||
/*
|
/*
|
||||||
* controldata.c
|
* controldata.c - functions for reading the pg_control file
|
||||||
* Copyright (c) 2ndQuadrant, 2010-2017
|
*
|
||||||
|
* The functions provided here enable repmgr to read a pg_control file
|
||||||
|
* in a version-indepent way, even if the PostgreSQL instance is not
|
||||||
|
* running. For that reason we can't use on the pg_control_*() functions
|
||||||
|
* provided in PostgreSQL 9.6 and later.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2ndQuadrant, 2010-2019
|
||||||
*
|
*
|
||||||
* Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
@@ -30,6 +36,53 @@
|
|||||||
|
|
||||||
static ControlFileInfo *get_controlfile(const char *DataDir);
|
static ControlFileInfo *get_controlfile(const char *DataDir);
|
||||||
|
|
||||||
|
int
|
||||||
|
get_pg_version(const char *data_directory, char *version_string)
|
||||||
|
{
|
||||||
|
char PgVersionPath[MAXPGPATH] = "";
|
||||||
|
FILE *fp = NULL;
|
||||||
|
char *endptr = NULL;
|
||||||
|
char file_version_string[MAX_VERSION_STRING] = "";
|
||||||
|
long file_major, file_minor;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
snprintf(PgVersionPath, MAXPGPATH, "%s/PG_VERSION", data_directory);
|
||||||
|
|
||||||
|
fp = fopen(PgVersionPath, "r");
|
||||||
|
|
||||||
|
if (fp == NULL)
|
||||||
|
{
|
||||||
|
log_warning(_("could not open file \"%s\" for reading"),
|
||||||
|
PgVersionPath);
|
||||||
|
log_detail("%s", strerror(errno));
|
||||||
|
return UNKNOWN_SERVER_VERSION_NUM;
|
||||||
|
}
|
||||||
|
|
||||||
|
file_version_string[0] = '\0';
|
||||||
|
|
||||||
|
ret = fscanf(fp, "%23s", file_version_string);
|
||||||
|
fclose(fp);
|
||||||
|
|
||||||
|
if (ret != 1 || endptr == file_version_string)
|
||||||
|
{
|
||||||
|
log_warning(_("unable to determine major version number from PG_VERSION"));
|
||||||
|
|
||||||
|
return UNKNOWN_SERVER_VERSION_NUM;
|
||||||
|
}
|
||||||
|
|
||||||
|
file_major = strtol(file_version_string, &endptr, 10);
|
||||||
|
file_minor = 0;
|
||||||
|
|
||||||
|
if (*endptr == '.')
|
||||||
|
file_minor = strtol(endptr + 1, NULL, 10);
|
||||||
|
|
||||||
|
if (version_string != NULL)
|
||||||
|
strncpy(version_string, file_version_string, MAX_VERSION_STRING);
|
||||||
|
|
||||||
|
return ((int) file_major * 10000) + ((int) file_minor * 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
uint64
|
uint64
|
||||||
get_system_identifier(const char *data_directory)
|
get_system_identifier(const char *data_directory)
|
||||||
{
|
{
|
||||||
@@ -37,18 +90,14 @@ get_system_identifier(const char *data_directory)
|
|||||||
uint64 system_identifier = UNKNOWN_SYSTEM_IDENTIFIER;
|
uint64 system_identifier = UNKNOWN_SYSTEM_IDENTIFIER;
|
||||||
|
|
||||||
control_file_info = get_controlfile(data_directory);
|
control_file_info = get_controlfile(data_directory);
|
||||||
|
system_identifier = control_file_info->system_identifier;
|
||||||
|
|
||||||
if (control_file_info->control_file_processed == true)
|
|
||||||
system_identifier = control_file_info->control_file->system_identifier;
|
|
||||||
else
|
|
||||||
system_identifier = UNKNOWN_SYSTEM_IDENTIFIER;
|
|
||||||
|
|
||||||
pfree(control_file_info->control_file);
|
|
||||||
pfree(control_file_info);
|
pfree(control_file_info);
|
||||||
|
|
||||||
return system_identifier;
|
return system_identifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
DBState
|
DBState
|
||||||
get_db_state(const char *data_directory)
|
get_db_state(const char *data_directory)
|
||||||
{
|
{
|
||||||
@@ -57,20 +106,15 @@ get_db_state(const char *data_directory)
|
|||||||
|
|
||||||
control_file_info = get_controlfile(data_directory);
|
control_file_info = get_controlfile(data_directory);
|
||||||
|
|
||||||
if (control_file_info->control_file_processed == true)
|
state = control_file_info->state;
|
||||||
state = control_file_info->control_file->state;
|
|
||||||
else
|
|
||||||
/* if we were unable to parse the control file, assume DB is shut down */
|
|
||||||
state = DB_SHUTDOWNED;
|
|
||||||
|
|
||||||
pfree(control_file_info->control_file);
|
|
||||||
pfree(control_file_info);
|
pfree(control_file_info);
|
||||||
|
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
extern XLogRecPtr
|
XLogRecPtr
|
||||||
get_latest_checkpoint_location(const char *data_directory)
|
get_latest_checkpoint_location(const char *data_directory)
|
||||||
{
|
{
|
||||||
ControlFileInfo *control_file_info = NULL;
|
ControlFileInfo *control_file_info = NULL;
|
||||||
@@ -78,12 +122,8 @@ get_latest_checkpoint_location(const char *data_directory)
|
|||||||
|
|
||||||
control_file_info = get_controlfile(data_directory);
|
control_file_info = get_controlfile(data_directory);
|
||||||
|
|
||||||
if (control_file_info->control_file_processed == false)
|
checkPoint = control_file_info->checkPoint;
|
||||||
return InvalidXLogRecPtr;
|
|
||||||
|
|
||||||
checkPoint = control_file_info->control_file->checkPoint;
|
|
||||||
|
|
||||||
pfree(control_file_info->control_file);
|
|
||||||
pfree(control_file_info);
|
pfree(control_file_info);
|
||||||
|
|
||||||
return checkPoint;
|
return checkPoint;
|
||||||
@@ -98,16 +138,8 @@ get_data_checksum_version(const char *data_directory)
|
|||||||
|
|
||||||
control_file_info = get_controlfile(data_directory);
|
control_file_info = get_controlfile(data_directory);
|
||||||
|
|
||||||
if (control_file_info->control_file_processed == false)
|
data_checksum_version = (int) control_file_info->data_checksum_version;
|
||||||
{
|
|
||||||
data_checksum_version = -1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
data_checksum_version = (int) control_file_info->control_file->data_checksum_version;
|
|
||||||
}
|
|
||||||
|
|
||||||
pfree(control_file_info->control_file);
|
|
||||||
pfree(control_file_info);
|
pfree(control_file_info);
|
||||||
|
|
||||||
return data_checksum_version;
|
return data_checksum_version;
|
||||||
@@ -134,38 +166,143 @@ describe_db_state(DBState state)
|
|||||||
case DB_IN_PRODUCTION:
|
case DB_IN_PRODUCTION:
|
||||||
return _("in production");
|
return _("in production");
|
||||||
}
|
}
|
||||||
|
|
||||||
return _("unrecognized status code");
|
return _("unrecognized status code");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TimeLineID
|
||||||
|
get_timeline(const char *data_directory)
|
||||||
|
{
|
||||||
|
ControlFileInfo *control_file_info = NULL;
|
||||||
|
TimeLineID timeline = -1;
|
||||||
|
|
||||||
|
control_file_info = get_controlfile(data_directory);
|
||||||
|
|
||||||
|
timeline = (int) control_file_info->timeline;
|
||||||
|
|
||||||
|
pfree(control_file_info);
|
||||||
|
|
||||||
|
return timeline;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TimeLineID
|
||||||
|
get_min_recovery_end_timeline(const char *data_directory)
|
||||||
|
{
|
||||||
|
ControlFileInfo *control_file_info = NULL;
|
||||||
|
TimeLineID timeline = -1;
|
||||||
|
|
||||||
|
control_file_info = get_controlfile(data_directory);
|
||||||
|
|
||||||
|
timeline = (int) control_file_info->minRecoveryPointTLI;
|
||||||
|
|
||||||
|
pfree(control_file_info);
|
||||||
|
|
||||||
|
return timeline;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
XLogRecPtr
|
||||||
|
get_min_recovery_location(const char *data_directory)
|
||||||
|
{
|
||||||
|
ControlFileInfo *control_file_info = NULL;
|
||||||
|
XLogRecPtr minRecoveryPoint = InvalidXLogRecPtr;
|
||||||
|
|
||||||
|
control_file_info = get_controlfile(data_directory);
|
||||||
|
|
||||||
|
minRecoveryPoint = control_file_info->minRecoveryPoint;
|
||||||
|
|
||||||
|
pfree(control_file_info);
|
||||||
|
|
||||||
|
return minRecoveryPoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* we maintain our own version of get_controlfile() as we need cross-version
|
* We maintain our own version of get_controlfile() as we need cross-version
|
||||||
* compatibility, and also don't care if the file isn't readable.
|
* compatibility, and also don't care if the file isn't readable.
|
||||||
*/
|
*/
|
||||||
static ControlFileInfo *
|
static ControlFileInfo *
|
||||||
get_controlfile(const char *DataDir)
|
get_controlfile(const char *DataDir)
|
||||||
{
|
{
|
||||||
|
char file_version_string[MAX_VERSION_STRING] = "";
|
||||||
ControlFileInfo *control_file_info;
|
ControlFileInfo *control_file_info;
|
||||||
int fd;
|
int fd, version_num;
|
||||||
char ControlFilePath[MAXPGPATH] = "";
|
char ControlFilePath[MAXPGPATH] = "";
|
||||||
|
void *ControlFileDataPtr = NULL;
|
||||||
|
int expected_size = 0;
|
||||||
|
|
||||||
control_file_info = palloc0(sizeof(ControlFileInfo));
|
control_file_info = palloc0(sizeof(ControlFileInfo));
|
||||||
|
|
||||||
|
/* set default values */
|
||||||
control_file_info->control_file_processed = false;
|
control_file_info->control_file_processed = false;
|
||||||
control_file_info->control_file = palloc0(sizeof(ControlFileData));
|
control_file_info->system_identifier = UNKNOWN_SYSTEM_IDENTIFIER;
|
||||||
|
control_file_info->state = DB_SHUTDOWNED;
|
||||||
|
control_file_info->checkPoint = InvalidXLogRecPtr;
|
||||||
|
control_file_info->data_checksum_version = -1;
|
||||||
|
control_file_info->timeline = -1;
|
||||||
|
control_file_info->minRecoveryPointTLI = -1;
|
||||||
|
control_file_info->minRecoveryPoint = InvalidXLogRecPtr;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read PG_VERSION, as we'll need to determine which struct to read
|
||||||
|
* the control file contents into
|
||||||
|
*/
|
||||||
|
|
||||||
|
version_num = get_pg_version(DataDir, file_version_string);
|
||||||
|
|
||||||
|
if (version_num == UNKNOWN_SERVER_VERSION_NUM)
|
||||||
|
{
|
||||||
|
log_warning(_("unable to determine server version number from PG_VERSION"));
|
||||||
|
return control_file_info;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (version_num < MIN_SUPPORTED_VERSION_NUM)
|
||||||
|
{
|
||||||
|
log_warning(_("data directory appears to be initialised for %s"),
|
||||||
|
file_version_string);
|
||||||
|
log_detail(_("minimum supported PostgreSQL version is %s"),
|
||||||
|
MIN_SUPPORTED_VERSION);
|
||||||
|
return control_file_info;
|
||||||
|
}
|
||||||
|
|
||||||
snprintf(ControlFilePath, MAXPGPATH, "%s/global/pg_control", DataDir);
|
snprintf(ControlFilePath, MAXPGPATH, "%s/global/pg_control", DataDir);
|
||||||
|
|
||||||
if ((fd = open(ControlFilePath, O_RDONLY | PG_BINARY, 0)) == -1)
|
if ((fd = open(ControlFilePath, O_RDONLY | PG_BINARY, 0)) == -1)
|
||||||
{
|
{
|
||||||
log_debug("could not open file \"%s\" for reading: %s",
|
log_warning(_("could not open file \"%s\" for reading"),
|
||||||
ControlFilePath, strerror(errno));
|
ControlFilePath);
|
||||||
|
log_detail("%s", strerror(errno));
|
||||||
return control_file_info;
|
return control_file_info;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (read(fd, control_file_info->control_file, sizeof(ControlFileData)) != sizeof(ControlFileData))
|
|
||||||
|
if (version_num >= 90500)
|
||||||
{
|
{
|
||||||
log_debug("could not read file \"%s\": %s",
|
expected_size = sizeof(ControlFileData95);
|
||||||
ControlFilePath, strerror(errno));
|
ControlFileDataPtr = palloc0(expected_size);
|
||||||
|
}
|
||||||
|
else if (version_num >= 90400)
|
||||||
|
{
|
||||||
|
expected_size = sizeof(ControlFileData94);
|
||||||
|
ControlFileDataPtr = palloc0(expected_size);
|
||||||
|
}
|
||||||
|
else if (version_num >= 90300)
|
||||||
|
{
|
||||||
|
expected_size = sizeof(ControlFileData93);
|
||||||
|
ControlFileDataPtr = palloc0(expected_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (read(fd, ControlFileDataPtr, expected_size) != expected_size)
|
||||||
|
{
|
||||||
|
log_warning(_("could not read file \"%s\""),
|
||||||
|
ControlFilePath);
|
||||||
|
log_detail("%s", strerror(errno));
|
||||||
|
|
||||||
|
close(fd);
|
||||||
|
|
||||||
return control_file_info;
|
return control_file_info;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -173,12 +310,57 @@ get_controlfile(const char *DataDir)
|
|||||||
|
|
||||||
control_file_info->control_file_processed = true;
|
control_file_info->control_file_processed = true;
|
||||||
|
|
||||||
|
if (version_num >= 110000)
|
||||||
|
{
|
||||||
|
ControlFileData11 *ptr = (struct ControlFileData11 *)ControlFileDataPtr;
|
||||||
|
control_file_info->system_identifier = ptr->system_identifier;
|
||||||
|
control_file_info->state = ptr->state;
|
||||||
|
control_file_info->checkPoint = ptr->checkPoint;
|
||||||
|
control_file_info->data_checksum_version = ptr->data_checksum_version;
|
||||||
|
control_file_info->timeline = ptr->checkPointCopy.ThisTimeLineID;
|
||||||
|
control_file_info->minRecoveryPointTLI = ptr->minRecoveryPointTLI;
|
||||||
|
control_file_info->minRecoveryPoint = ptr->minRecoveryPoint;
|
||||||
|
}
|
||||||
|
else if (version_num >= 90500)
|
||||||
|
{
|
||||||
|
ControlFileData95 *ptr = (struct ControlFileData95 *)ControlFileDataPtr;
|
||||||
|
control_file_info->system_identifier = ptr->system_identifier;
|
||||||
|
control_file_info->state = ptr->state;
|
||||||
|
control_file_info->checkPoint = ptr->checkPoint;
|
||||||
|
control_file_info->data_checksum_version = ptr->data_checksum_version;
|
||||||
|
control_file_info->timeline = ptr->checkPointCopy.ThisTimeLineID;
|
||||||
|
control_file_info->minRecoveryPointTLI = ptr->minRecoveryPointTLI;
|
||||||
|
control_file_info->minRecoveryPoint = ptr->minRecoveryPoint;
|
||||||
|
}
|
||||||
|
else if (version_num >= 90400)
|
||||||
|
{
|
||||||
|
ControlFileData94 *ptr = (struct ControlFileData94 *)ControlFileDataPtr;
|
||||||
|
control_file_info->system_identifier = ptr->system_identifier;
|
||||||
|
control_file_info->state = ptr->state;
|
||||||
|
control_file_info->checkPoint = ptr->checkPoint;
|
||||||
|
control_file_info->data_checksum_version = ptr->data_checksum_version;
|
||||||
|
control_file_info->timeline = ptr->checkPointCopy.ThisTimeLineID;
|
||||||
|
control_file_info->minRecoveryPointTLI = ptr->minRecoveryPointTLI;
|
||||||
|
control_file_info->minRecoveryPoint = ptr->minRecoveryPoint;
|
||||||
|
}
|
||||||
|
else if (version_num >= 90300)
|
||||||
|
{
|
||||||
|
ControlFileData93 *ptr = (struct ControlFileData93 *)ControlFileDataPtr;
|
||||||
|
control_file_info->system_identifier = ptr->system_identifier;
|
||||||
|
control_file_info->state = ptr->state;
|
||||||
|
control_file_info->checkPoint = ptr->checkPoint;
|
||||||
|
control_file_info->data_checksum_version = ptr->data_checksum_version;
|
||||||
|
control_file_info->timeline = ptr->checkPointCopy.ThisTimeLineID;
|
||||||
|
control_file_info->minRecoveryPointTLI = ptr->minRecoveryPointTLI;
|
||||||
|
control_file_info->minRecoveryPoint = ptr->minRecoveryPoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
pfree(ControlFileDataPtr);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We don't check the CRC here as we're potentially checking a pg_control
|
* We don't check the CRC here as we're potentially checking a pg_control
|
||||||
* file from a different PostgreSQL version to the one repmgr was compiled
|
* file from a different PostgreSQL version to the one repmgr was compiled
|
||||||
* against. However we're only interested in the first few fields, which
|
* against.
|
||||||
* should be constant across supported versions
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
return control_file_info;
|
return control_file_info;
|
||||||
|
|||||||
323
controldata.h
323
controldata.h
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* controldata.h
|
* controldata.h
|
||||||
* Copyright (c) 2ndQuadrant, 2010-2017
|
* Copyright (c) 2ndQuadrant, 2010-2019
|
||||||
*
|
*
|
||||||
* Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
@@ -12,16 +12,335 @@
|
|||||||
#include "postgres_fe.h"
|
#include "postgres_fe.h"
|
||||||
#include "catalog/pg_control.h"
|
#include "catalog/pg_control.h"
|
||||||
|
|
||||||
|
#define MAX_VERSION_STRING 24
|
||||||
|
/*
|
||||||
|
* A simplified representation of pg_control containing only those fields
|
||||||
|
* required by repmgr.
|
||||||
|
*/
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
bool control_file_processed;
|
bool control_file_processed;
|
||||||
ControlFileData *control_file;
|
uint64 system_identifier;
|
||||||
|
DBState state;
|
||||||
|
XLogRecPtr checkPoint;
|
||||||
|
uint32 data_checksum_version;
|
||||||
|
TimeLineID timeline;
|
||||||
|
TimeLineID minRecoveryPointTLI;
|
||||||
|
XLogRecPtr minRecoveryPoint;
|
||||||
} ControlFileInfo;
|
} ControlFileInfo;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Same for 9.3, 9.4 */
|
||||||
|
typedef struct CheckPoint93
|
||||||
|
{
|
||||||
|
XLogRecPtr redo; /* next RecPtr available when we began to
|
||||||
|
* create CheckPoint (i.e. REDO start point) */
|
||||||
|
TimeLineID ThisTimeLineID; /* current TLI */
|
||||||
|
TimeLineID PrevTimeLineID; /* previous TLI, if this record begins a new
|
||||||
|
* timeline (equals ThisTimeLineID otherwise) */
|
||||||
|
bool fullPageWrites; /* current full_page_writes */
|
||||||
|
uint32 nextXidEpoch; /* higher-order bits of nextXid */
|
||||||
|
TransactionId nextXid; /* next free XID */
|
||||||
|
Oid nextOid; /* next free OID */
|
||||||
|
MultiXactId nextMulti; /* next free MultiXactId */
|
||||||
|
MultiXactOffset nextMultiOffset; /* next free MultiXact offset */
|
||||||
|
TransactionId oldestXid; /* cluster-wide minimum datfrozenxid */
|
||||||
|
Oid oldestXidDB; /* database with minimum datfrozenxid */
|
||||||
|
MultiXactId oldestMulti; /* cluster-wide minimum datminmxid */
|
||||||
|
Oid oldestMultiDB; /* database with minimum datminmxid */
|
||||||
|
pg_time_t time; /* time stamp of checkpoint */
|
||||||
|
|
||||||
|
TransactionId oldestActiveXid;
|
||||||
|
} CheckPoint93;
|
||||||
|
|
||||||
|
|
||||||
|
/* Same for 9.5, 9.6, 10, HEAD */
|
||||||
|
typedef struct CheckPoint95
|
||||||
|
{
|
||||||
|
XLogRecPtr redo; /* next RecPtr available when we began to
|
||||||
|
* create CheckPoint (i.e. REDO start point) */
|
||||||
|
TimeLineID ThisTimeLineID; /* current TLI */
|
||||||
|
TimeLineID PrevTimeLineID; /* previous TLI, if this record begins a new
|
||||||
|
* timeline (equals ThisTimeLineID otherwise) */
|
||||||
|
bool fullPageWrites; /* current full_page_writes */
|
||||||
|
uint32 nextXidEpoch; /* higher-order bits of nextXid */
|
||||||
|
TransactionId nextXid; /* next free XID */
|
||||||
|
Oid nextOid; /* next free OID */
|
||||||
|
MultiXactId nextMulti; /* next free MultiXactId */
|
||||||
|
MultiXactOffset nextMultiOffset; /* next free MultiXact offset */
|
||||||
|
TransactionId oldestXid; /* cluster-wide minimum datfrozenxid */
|
||||||
|
Oid oldestXidDB; /* database with minimum datfrozenxid */
|
||||||
|
MultiXactId oldestMulti; /* cluster-wide minimum datminmxid */
|
||||||
|
Oid oldestMultiDB; /* database with minimum datminmxid */
|
||||||
|
pg_time_t time; /* time stamp of checkpoint */
|
||||||
|
TransactionId oldestCommitTsXid; /* oldest Xid with valid commit
|
||||||
|
* timestamp */
|
||||||
|
TransactionId newestCommitTsXid; /* newest Xid with valid commit
|
||||||
|
* timestamp */
|
||||||
|
|
||||||
|
TransactionId oldestActiveXid;
|
||||||
|
} CheckPoint95;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct ControlFileData93
|
||||||
|
{
|
||||||
|
uint64 system_identifier;
|
||||||
|
|
||||||
|
uint32 pg_control_version; /* PG_CONTROL_VERSION */
|
||||||
|
uint32 catalog_version_no; /* see catversion.h */
|
||||||
|
|
||||||
|
DBState state; /* see enum above */
|
||||||
|
pg_time_t time; /* time stamp of last pg_control update */
|
||||||
|
XLogRecPtr checkPoint; /* last check point record ptr */
|
||||||
|
XLogRecPtr prevCheckPoint; /* previous check point record ptr */
|
||||||
|
|
||||||
|
CheckPoint93 checkPointCopy; /* copy of last check point record */
|
||||||
|
|
||||||
|
XLogRecPtr unloggedLSN; /* current fake LSN value, for unlogged rels */
|
||||||
|
|
||||||
|
XLogRecPtr minRecoveryPoint;
|
||||||
|
TimeLineID minRecoveryPointTLI;
|
||||||
|
XLogRecPtr backupStartPoint;
|
||||||
|
XLogRecPtr backupEndPoint;
|
||||||
|
bool backupEndRequired;
|
||||||
|
|
||||||
|
int wal_level;
|
||||||
|
int MaxConnections;
|
||||||
|
int max_prepared_xacts;
|
||||||
|
int max_locks_per_xact;
|
||||||
|
|
||||||
|
uint32 maxAlign; /* alignment requirement for tuples */
|
||||||
|
double floatFormat; /* constant 1234567.0 */
|
||||||
|
|
||||||
|
uint32 blcksz; /* data block size for this DB */
|
||||||
|
uint32 relseg_size; /* blocks per segment of large relation */
|
||||||
|
|
||||||
|
uint32 xlog_blcksz; /* block size within WAL files */
|
||||||
|
uint32 xlog_seg_size; /* size of each WAL segment */
|
||||||
|
|
||||||
|
uint32 nameDataLen; /* catalog name field width */
|
||||||
|
uint32 indexMaxKeys; /* max number of columns in an index */
|
||||||
|
|
||||||
|
uint32 toast_max_chunk_size; /* chunk size in TOAST tables */
|
||||||
|
|
||||||
|
/* flag indicating internal format of timestamp, interval, time */
|
||||||
|
bool enableIntTimes; /* int64 storage enabled? */
|
||||||
|
|
||||||
|
/* flags indicating pass-by-value status of various types */
|
||||||
|
bool float4ByVal; /* float4 pass-by-value? */
|
||||||
|
bool float8ByVal; /* float8, int8, etc pass-by-value? */
|
||||||
|
|
||||||
|
/* Are data pages protected by checksums? Zero if no checksum version */
|
||||||
|
uint32 data_checksum_version;
|
||||||
|
|
||||||
|
} ControlFileData93;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Following field added since 9.3:
|
||||||
|
*
|
||||||
|
* int max_worker_processes;
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct ControlFileData94
|
||||||
|
{
|
||||||
|
uint64 system_identifier;
|
||||||
|
|
||||||
|
uint32 pg_control_version; /* PG_CONTROL_VERSION */
|
||||||
|
uint32 catalog_version_no; /* see catversion.h */
|
||||||
|
|
||||||
|
DBState state; /* see enum above */
|
||||||
|
pg_time_t time; /* time stamp of last pg_control update */
|
||||||
|
XLogRecPtr checkPoint; /* last check point record ptr */
|
||||||
|
XLogRecPtr prevCheckPoint; /* previous check point record ptr */
|
||||||
|
|
||||||
|
CheckPoint93 checkPointCopy; /* copy of last check point record */
|
||||||
|
|
||||||
|
XLogRecPtr unloggedLSN; /* current fake LSN value, for unlogged rels */
|
||||||
|
|
||||||
|
XLogRecPtr minRecoveryPoint;
|
||||||
|
TimeLineID minRecoveryPointTLI;
|
||||||
|
XLogRecPtr backupStartPoint;
|
||||||
|
XLogRecPtr backupEndPoint;
|
||||||
|
bool backupEndRequired;
|
||||||
|
|
||||||
|
int wal_level;
|
||||||
|
bool wal_log_hints;
|
||||||
|
int MaxConnections;
|
||||||
|
int max_worker_processes;
|
||||||
|
int max_prepared_xacts;
|
||||||
|
int max_locks_per_xact;
|
||||||
|
|
||||||
|
uint32 maxAlign; /* alignment requirement for tuples */
|
||||||
|
double floatFormat; /* constant 1234567.0 */
|
||||||
|
|
||||||
|
uint32 blcksz; /* data block size for this DB */
|
||||||
|
uint32 relseg_size; /* blocks per segment of large relation */
|
||||||
|
|
||||||
|
uint32 xlog_blcksz; /* block size within WAL files */
|
||||||
|
uint32 xlog_seg_size; /* size of each WAL segment */
|
||||||
|
|
||||||
|
uint32 nameDataLen; /* catalog name field width */
|
||||||
|
uint32 indexMaxKeys; /* max number of columns in an index */
|
||||||
|
|
||||||
|
uint32 toast_max_chunk_size; /* chunk size in TOAST tables */
|
||||||
|
uint32 loblksize; /* chunk size in pg_largeobject */
|
||||||
|
|
||||||
|
bool enableIntTimes; /* int64 storage enabled? */
|
||||||
|
|
||||||
|
bool float4ByVal; /* float4 pass-by-value? */
|
||||||
|
bool float8ByVal; /* float8, int8, etc pass-by-value? */
|
||||||
|
|
||||||
|
/* Are data pages protected by checksums? Zero if no checksum version */
|
||||||
|
uint32 data_checksum_version;
|
||||||
|
|
||||||
|
} ControlFileData94;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Following field added since 9.4:
|
||||||
|
*
|
||||||
|
* bool track_commit_timestamp;
|
||||||
|
*
|
||||||
|
* Unchanged in 9.6
|
||||||
|
*
|
||||||
|
* In 10, following field appended *after* "data_checksum_version":
|
||||||
|
*
|
||||||
|
* char mock_authentication_nonce[MOCK_AUTH_NONCE_LEN];
|
||||||
|
*
|
||||||
|
* (but we don't care about that)
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct ControlFileData95
|
||||||
|
{
|
||||||
|
uint64 system_identifier;
|
||||||
|
|
||||||
|
uint32 pg_control_version; /* PG_CONTROL_VERSION */
|
||||||
|
uint32 catalog_version_no; /* see catversion.h */
|
||||||
|
|
||||||
|
DBState state; /* see enum above */
|
||||||
|
pg_time_t time; /* time stamp of last pg_control update */
|
||||||
|
XLogRecPtr checkPoint; /* last check point record ptr */
|
||||||
|
XLogRecPtr prevCheckPoint; /* previous check point record ptr */
|
||||||
|
|
||||||
|
CheckPoint95 checkPointCopy; /* copy of last check point record */
|
||||||
|
|
||||||
|
XLogRecPtr unloggedLSN; /* current fake LSN value, for unlogged rels */
|
||||||
|
|
||||||
|
XLogRecPtr minRecoveryPoint;
|
||||||
|
TimeLineID minRecoveryPointTLI;
|
||||||
|
XLogRecPtr backupStartPoint;
|
||||||
|
XLogRecPtr backupEndPoint;
|
||||||
|
bool backupEndRequired;
|
||||||
|
|
||||||
|
int wal_level;
|
||||||
|
bool wal_log_hints;
|
||||||
|
int MaxConnections;
|
||||||
|
int max_worker_processes;
|
||||||
|
int max_prepared_xacts;
|
||||||
|
int max_locks_per_xact;
|
||||||
|
bool track_commit_timestamp;
|
||||||
|
|
||||||
|
uint32 maxAlign; /* alignment requirement for tuples */
|
||||||
|
double floatFormat; /* constant 1234567.0 */
|
||||||
|
|
||||||
|
uint32 blcksz; /* data block size for this DB */
|
||||||
|
uint32 relseg_size; /* blocks per segment of large relation */
|
||||||
|
|
||||||
|
uint32 xlog_blcksz; /* block size within WAL files */
|
||||||
|
uint32 xlog_seg_size; /* size of each WAL segment */
|
||||||
|
|
||||||
|
uint32 nameDataLen; /* catalog name field width */
|
||||||
|
uint32 indexMaxKeys; /* max number of columns in an index */
|
||||||
|
|
||||||
|
uint32 toast_max_chunk_size; /* chunk size in TOAST tables */
|
||||||
|
uint32 loblksize; /* chunk size in pg_largeobject */
|
||||||
|
|
||||||
|
bool enableIntTimes; /* int64 storage enabled? */
|
||||||
|
|
||||||
|
bool float4ByVal; /* float4 pass-by-value? */
|
||||||
|
bool float8ByVal; /* float8, int8, etc pass-by-value? */
|
||||||
|
|
||||||
|
uint32 data_checksum_version;
|
||||||
|
|
||||||
|
} ControlFileData95;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Following field removed in 11:
|
||||||
|
*
|
||||||
|
* XLogRecPtr prevCheckPoint;
|
||||||
|
*
|
||||||
|
* In 10, following field appended *after* "data_checksum_version":
|
||||||
|
*
|
||||||
|
* char mock_authentication_nonce[MOCK_AUTH_NONCE_LEN];
|
||||||
|
*
|
||||||
|
* (but we don't care about that)
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct ControlFileData11
|
||||||
|
{
|
||||||
|
uint64 system_identifier;
|
||||||
|
|
||||||
|
uint32 pg_control_version; /* PG_CONTROL_VERSION */
|
||||||
|
uint32 catalog_version_no; /* see catversion.h */
|
||||||
|
|
||||||
|
DBState state; /* see enum above */
|
||||||
|
pg_time_t time; /* time stamp of last pg_control update */
|
||||||
|
XLogRecPtr checkPoint; /* last check point record ptr */
|
||||||
|
|
||||||
|
CheckPoint95 checkPointCopy; /* copy of last check point record */
|
||||||
|
|
||||||
|
XLogRecPtr unloggedLSN; /* current fake LSN value, for unlogged rels */
|
||||||
|
|
||||||
|
XLogRecPtr minRecoveryPoint;
|
||||||
|
TimeLineID minRecoveryPointTLI;
|
||||||
|
XLogRecPtr backupStartPoint;
|
||||||
|
XLogRecPtr backupEndPoint;
|
||||||
|
bool backupEndRequired;
|
||||||
|
|
||||||
|
int wal_level;
|
||||||
|
bool wal_log_hints;
|
||||||
|
int MaxConnections;
|
||||||
|
int max_worker_processes;
|
||||||
|
int max_prepared_xacts;
|
||||||
|
int max_locks_per_xact;
|
||||||
|
bool track_commit_timestamp;
|
||||||
|
|
||||||
|
uint32 maxAlign; /* alignment requirement for tuples */
|
||||||
|
double floatFormat; /* constant 1234567.0 */
|
||||||
|
|
||||||
|
uint32 blcksz; /* data block size for this DB */
|
||||||
|
uint32 relseg_size; /* blocks per segment of large relation */
|
||||||
|
|
||||||
|
uint32 xlog_blcksz; /* block size within WAL files */
|
||||||
|
uint32 xlog_seg_size; /* size of each WAL segment */
|
||||||
|
|
||||||
|
uint32 nameDataLen; /* catalog name field width */
|
||||||
|
uint32 indexMaxKeys; /* max number of columns in an index */
|
||||||
|
|
||||||
|
uint32 toast_max_chunk_size; /* chunk size in TOAST tables */
|
||||||
|
uint32 loblksize; /* chunk size in pg_largeobject */
|
||||||
|
|
||||||
|
bool enableIntTimes; /* int64 storage enabled? */
|
||||||
|
|
||||||
|
bool float4ByVal; /* float4 pass-by-value? */
|
||||||
|
bool float8ByVal; /* float8, int8, etc pass-by-value? */
|
||||||
|
|
||||||
|
uint32 data_checksum_version;
|
||||||
|
|
||||||
|
} ControlFileData11;
|
||||||
|
|
||||||
|
|
||||||
|
extern int get_pg_version(const char *data_directory, char *version_string);
|
||||||
extern DBState get_db_state(const char *data_directory);
|
extern DBState get_db_state(const char *data_directory);
|
||||||
extern const char *describe_db_state(DBState state);
|
extern const char *describe_db_state(DBState state);
|
||||||
extern int get_data_checksum_version(const char *data_directory);
|
extern int get_data_checksum_version(const char *data_directory);
|
||||||
extern uint64 get_system_identifier(const char *data_directory);
|
extern uint64 get_system_identifier(const char *data_directory);
|
||||||
extern XLogRecPtr get_latest_checkpoint_location(const char *data_directory);
|
extern XLogRecPtr get_latest_checkpoint_location(const char *data_directory);
|
||||||
|
extern TimeLineID get_timeline(const char *data_directory);
|
||||||
|
extern TimeLineID get_min_recovery_end_timeline(const char *data_directory);
|
||||||
|
extern XLogRecPtr get_min_recovery_location(const char *data_directory);
|
||||||
|
|
||||||
#endif /* _CONTROLDATA_H_ */
|
#endif /* _CONTROLDATA_H_ */
|
||||||
|
|||||||
210
dbutils.h
210
dbutils.h
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* dbutils.h
|
* dbutils.h
|
||||||
*
|
*
|
||||||
* Copyright (c) 2ndQuadrant, 2010-2017
|
* Copyright (c) 2ndQuadrant, 2010-2019
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -20,6 +20,7 @@
|
|||||||
#ifndef _REPMGR_DBUTILS_H_
|
#ifndef _REPMGR_DBUTILS_H_
|
||||||
#define _REPMGR_DBUTILS_H_
|
#define _REPMGR_DBUTILS_H_
|
||||||
|
|
||||||
|
#include "access/timeline.h"
|
||||||
#include "access/xlogdefs.h"
|
#include "access/xlogdefs.h"
|
||||||
#include "pqexpbuffer.h"
|
#include "pqexpbuffer.h"
|
||||||
#include "portability/instr_time.h"
|
#include "portability/instr_time.h"
|
||||||
@@ -28,8 +29,10 @@
|
|||||||
#include "strutil.h"
|
#include "strutil.h"
|
||||||
#include "voting.h"
|
#include "voting.h"
|
||||||
|
|
||||||
#define REPMGR_NODES_COLUMNS "node_id, type, upstream_node_id, node_name, conninfo, repluser, slot_name, location, priority, active, config_file, '' AS upstream_node_name "
|
#define REPMGR_NODES_COLUMNS "n.node_id, n.type, n.upstream_node_id, n.node_name, n.conninfo, n.repluser, n.slot_name, n.location, n.priority, n.active, n.config_file, '' AS upstream_node_name "
|
||||||
#define BDR_NODES_COLUMNS "node_sysid, node_timeline, node_dboid, node_status, node_name, node_local_dsn, node_init_from_dsn, node_read_only, node_seq_id"
|
#define BDR2_NODES_COLUMNS "node_sysid, node_timeline, node_dboid, node_name, node_local_dsn, ''"
|
||||||
|
#define BDR3_NODES_COLUMNS "ns.node_id, 0, 0, ns.node_name, ns.interface_connstr, ns.peer_state_name"
|
||||||
|
|
||||||
|
|
||||||
#define ERRBUFF_SIZE 512
|
#define ERRBUFF_SIZE 512
|
||||||
|
|
||||||
@@ -38,12 +41,14 @@ typedef enum
|
|||||||
UNKNOWN = 0,
|
UNKNOWN = 0,
|
||||||
PRIMARY,
|
PRIMARY,
|
||||||
STANDBY,
|
STANDBY,
|
||||||
|
WITNESS,
|
||||||
BDR
|
BDR
|
||||||
} t_server_type;
|
} t_server_type;
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
REPMGR_INSTALLED = 0,
|
REPMGR_INSTALLED = 0,
|
||||||
|
REPMGR_OLD_VERSION_INSTALLED,
|
||||||
REPMGR_AVAILABLE,
|
REPMGR_AVAILABLE,
|
||||||
REPMGR_UNAVAILABLE,
|
REPMGR_UNAVAILABLE,
|
||||||
REPMGR_UNKNOWN
|
REPMGR_UNKNOWN
|
||||||
@@ -73,17 +78,19 @@ typedef enum
|
|||||||
{
|
{
|
||||||
NODE_STATUS_UNKNOWN = -1,
|
NODE_STATUS_UNKNOWN = -1,
|
||||||
NODE_STATUS_UP,
|
NODE_STATUS_UP,
|
||||||
|
NODE_STATUS_SHUTTING_DOWN,
|
||||||
NODE_STATUS_DOWN,
|
NODE_STATUS_DOWN,
|
||||||
NODE_STATUS_UNCLEAN_SHUTDOWN
|
NODE_STATUS_UNCLEAN_SHUTDOWN,
|
||||||
|
NODE_STATUS_REJECTED
|
||||||
} NodeStatus;
|
} NodeStatus;
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
VR_VOTE_REFUSED = -1,
|
CONN_UNKNOWN = -1,
|
||||||
VR_POSITIVE_VOTE,
|
CONN_OK,
|
||||||
VR_NEGATIVE_VOTE
|
CONN_BAD,
|
||||||
} VoteRequestResult;
|
CONN_ERROR
|
||||||
|
} ConnectionStatus;
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
@@ -92,6 +99,32 @@ typedef enum
|
|||||||
SLOT_ACTIVE
|
SLOT_ACTIVE
|
||||||
} ReplSlotStatus;
|
} ReplSlotStatus;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
BACKUP_STATE_UNKNOWN = -1,
|
||||||
|
BACKUP_STATE_IN_BACKUP,
|
||||||
|
BACKUP_STATE_NO_BACKUP
|
||||||
|
} BackupState;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Struct to store extension version information
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct s_extension_versions {
|
||||||
|
char default_version[8];
|
||||||
|
int default_version_num;
|
||||||
|
char installed_version[8];
|
||||||
|
int installed_version_num;
|
||||||
|
} t_extension_versions;
|
||||||
|
|
||||||
|
#define T_EXTENSION_VERSIONS_INITIALIZER { \
|
||||||
|
"", \
|
||||||
|
UNKNOWN_SERVER_VERSION_NUM, \
|
||||||
|
"", \
|
||||||
|
UNKNOWN_SERVER_VERSION_NUM \
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Struct to store node information
|
* Struct to store node information
|
||||||
*/
|
*/
|
||||||
@@ -101,8 +134,8 @@ typedef struct s_node_info
|
|||||||
int node_id;
|
int node_id;
|
||||||
int upstream_node_id;
|
int upstream_node_id;
|
||||||
t_server_type type;
|
t_server_type type;
|
||||||
char node_name[MAXLEN];
|
char node_name[NAMEDATALEN];
|
||||||
char upstream_node_name[MAXLEN];
|
char upstream_node_name[NAMEDATALEN];
|
||||||
char conninfo[MAXLEN];
|
char conninfo[MAXLEN];
|
||||||
char repluser[NAMEDATALEN];
|
char repluser[NAMEDATALEN];
|
||||||
char location[MAXLEN];
|
char location[MAXLEN];
|
||||||
@@ -151,7 +184,7 @@ typedef struct s_node_info
|
|||||||
MS_NORMAL, \
|
MS_NORMAL, \
|
||||||
NULL, \
|
NULL, \
|
||||||
/* for ad-hoc use e.g. when working with a list of nodes */ \
|
/* for ad-hoc use e.g. when working with a list of nodes */ \
|
||||||
"", true, true \
|
"", true, true, \
|
||||||
/* various statistics */ \
|
/* various statistics */ \
|
||||||
-1, -1, -1, -1, -1, -1 \
|
-1, -1, -1, -1, -1, -1 \
|
||||||
}
|
}
|
||||||
@@ -181,11 +214,13 @@ typedef struct s_event_info
|
|||||||
{
|
{
|
||||||
char *node_name;
|
char *node_name;
|
||||||
char *conninfo_str;
|
char *conninfo_str;
|
||||||
|
int node_id;
|
||||||
} t_event_info;
|
} t_event_info;
|
||||||
|
|
||||||
#define T_EVENT_INFO_INITIALIZER { \
|
#define T_EVENT_INFO_INITIALIZER { \
|
||||||
NULL, \
|
NULL, \
|
||||||
NULL \
|
NULL, \
|
||||||
|
UNKNOWN_NODE_ID \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -233,18 +268,14 @@ typedef struct s_bdr_node_info
|
|||||||
char node_sysid[MAXLEN];
|
char node_sysid[MAXLEN];
|
||||||
uint32 node_timeline;
|
uint32 node_timeline;
|
||||||
uint32 node_dboid;
|
uint32 node_dboid;
|
||||||
char node_status;
|
|
||||||
char node_name[MAXLEN];
|
char node_name[MAXLEN];
|
||||||
char node_local_dsn[MAXLEN];
|
char node_local_dsn[MAXLEN];
|
||||||
char node_init_from_dsn[MAXLEN];
|
char peer_state_name[MAXLEN];
|
||||||
bool read_only;
|
|
||||||
uint32 node_seq_id;
|
|
||||||
} t_bdr_node_info;
|
} t_bdr_node_info;
|
||||||
|
|
||||||
#define T_BDR_NODE_INFO_INITIALIZER { \
|
#define T_BDR_NODE_INFO_INITIALIZER { \
|
||||||
"", InvalidOid, InvalidOid, \
|
"", InvalidOid, InvalidOid, \
|
||||||
'?', "", "", "", \
|
"", "", "" \
|
||||||
false, -1 \
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -271,22 +302,16 @@ typedef struct BdrNodeInfoList
|
|||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
char current_timestamp[MAXLEN];
|
char current_timestamp[MAXLEN];
|
||||||
uint64 last_wal_receive_lsn;
|
bool in_recovery;
|
||||||
uint64 last_wal_replay_lsn;
|
XLogRecPtr last_wal_receive_lsn;
|
||||||
|
XLogRecPtr last_wal_replay_lsn;
|
||||||
char last_xact_replay_timestamp[MAXLEN];
|
char last_xact_replay_timestamp[MAXLEN];
|
||||||
int replication_lag_time;
|
int replication_lag_time;
|
||||||
bool receiving_streamed_wal;
|
bool receiving_streamed_wal;
|
||||||
|
bool wal_replay_paused;
|
||||||
|
int upstream_last_seen;
|
||||||
} ReplInfo;
|
} ReplInfo;
|
||||||
|
|
||||||
#define T_REPLINFO_INTIALIZER { \
|
|
||||||
"", \
|
|
||||||
InvalidXLogRecPtr, \
|
|
||||||
InvalidXLogRecPtr, \
|
|
||||||
"", \
|
|
||||||
0 \
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
char filepath[MAXPGPATH];
|
char filepath[MAXPGPATH];
|
||||||
@@ -317,9 +342,24 @@ typedef struct
|
|||||||
UNKNOWN_TIMELINE_ID, \
|
UNKNOWN_TIMELINE_ID, \
|
||||||
InvalidXLogRecPtr \
|
InvalidXLogRecPtr \
|
||||||
}
|
}
|
||||||
/* global variables */
|
|
||||||
|
|
||||||
extern int server_version_num;
|
|
||||||
|
typedef struct RepmgrdInfo {
|
||||||
|
int node_id;
|
||||||
|
int pid;
|
||||||
|
char pid_text[MAXLEN];
|
||||||
|
char pid_file[MAXLEN];
|
||||||
|
bool pg_running;
|
||||||
|
char pg_running_text[MAXLEN];
|
||||||
|
RecoveryType recovery_type;
|
||||||
|
bool running;
|
||||||
|
char repmgrd_running[MAXLEN];
|
||||||
|
bool paused;
|
||||||
|
bool wal_paused_pending_wal;
|
||||||
|
int upstream_last_seen;
|
||||||
|
char upstream_last_seen_text[MAXLEN];
|
||||||
|
} RepmgrdInfo;
|
||||||
|
|
||||||
|
|
||||||
/* macros */
|
/* macros */
|
||||||
|
|
||||||
@@ -336,26 +376,22 @@ __attribute__((format(PG_PRINTF_ATTRIBUTE, 3, 4)));
|
|||||||
bool atobool(const char *value);
|
bool atobool(const char *value);
|
||||||
|
|
||||||
/* connection functions */
|
/* connection functions */
|
||||||
PGconn *establish_db_connection(const char *conninfo,
|
PGconn *establish_db_connection(const char *conninfo,
|
||||||
const bool exit_on_error);
|
const bool exit_on_error);
|
||||||
PGconn *establish_db_connection_quiet(const char *conninfo);
|
PGconn *establish_db_connection_quiet(const char *conninfo);
|
||||||
PGconn *establish_db_connection_as_user(const char *conninfo,
|
PGconn *establish_db_connection_by_params(t_conninfo_param_list *param_list,
|
||||||
const char *user,
|
|
||||||
const bool exit_on_error);
|
|
||||||
|
|
||||||
PGconn *establish_db_connection_by_params(t_conninfo_param_list *param_list,
|
|
||||||
const bool exit_on_error);
|
const bool exit_on_error);
|
||||||
PGconn *establish_primary_db_connection(PGconn *conn,
|
PGconn *establish_primary_db_connection(PGconn *conn,
|
||||||
const bool exit_on_error);
|
const bool exit_on_error);
|
||||||
|
|
||||||
PGconn *get_primary_connection(PGconn *standby_conn, int *primary_id, char *primary_conninfo_out);
|
PGconn *get_primary_connection(PGconn *standby_conn, int *primary_id, char *primary_conninfo_out);
|
||||||
PGconn *get_primary_connection_quiet(PGconn *standby_conn, int *primary_id, char *primary_conninfo_out);
|
PGconn *get_primary_connection_quiet(PGconn *standby_conn, int *primary_id, char *primary_conninfo_out);
|
||||||
|
|
||||||
bool is_superuser_connection(PGconn *conn, t_connection_user *userinfo);
|
bool is_superuser_connection(PGconn *conn, t_connection_user *userinfo);
|
||||||
|
void close_connection(PGconn **conn);
|
||||||
|
|
||||||
/* conninfo manipulation functions */
|
/* conninfo manipulation functions */
|
||||||
bool get_conninfo_value(const char *conninfo, const char *keyword, char *output);
|
bool get_conninfo_value(const char *conninfo, const char *keyword, char *output);
|
||||||
|
bool get_conninfo_default_value(const char *param, char *output, int maxlen);
|
||||||
void initialize_conninfo_params(t_conninfo_param_list *param_list, bool set_defaults);
|
void initialize_conninfo_params(t_conninfo_param_list *param_list, bool set_defaults);
|
||||||
void free_conninfo_params(t_conninfo_param_list *param_list);
|
void free_conninfo_params(t_conninfo_param_list *param_list);
|
||||||
void copy_conninfo_params(t_conninfo_param_list *dest_list, t_conninfo_param_list *source_list);
|
void copy_conninfo_params(t_conninfo_param_list *dest_list, t_conninfo_param_list *source_list);
|
||||||
@@ -363,68 +399,93 @@ void conn_to_param_list(PGconn *conn, t_conninfo_param_list *param_list);
|
|||||||
void param_set(t_conninfo_param_list *param_list, const char *param, const char *value);
|
void param_set(t_conninfo_param_list *param_list, const char *param, const char *value);
|
||||||
void param_set_ine(t_conninfo_param_list *param_list, const char *param, const char *value);
|
void param_set_ine(t_conninfo_param_list *param_list, const char *param, const char *value);
|
||||||
char *param_get(t_conninfo_param_list *param_list, const char *param);
|
char *param_get(t_conninfo_param_list *param_list, const char *param);
|
||||||
bool parse_conninfo_string(const char *conninfo_str, t_conninfo_param_list *param_list, char *errmsg, bool ignore_local_params);
|
bool parse_conninfo_string(const char *conninfo_str, t_conninfo_param_list *param_list, char **errmsg, bool ignore_local_params);
|
||||||
char *param_list_to_string(t_conninfo_param_list *param_list);
|
char *param_list_to_string(t_conninfo_param_list *param_list);
|
||||||
|
char *normalize_conninfo_string(const char *conninfo_str);
|
||||||
|
bool has_passfile(void);
|
||||||
|
|
||||||
|
|
||||||
/* transaction functions */
|
/* transaction functions */
|
||||||
bool begin_transaction(PGconn *conn);
|
bool begin_transaction(PGconn *conn);
|
||||||
bool commit_transaction(PGconn *conn);
|
bool commit_transaction(PGconn *conn);
|
||||||
bool rollback_transaction(PGconn *conn);
|
bool rollback_transaction(PGconn *conn);
|
||||||
bool check_cluster_schema(PGconn *conn);
|
|
||||||
|
|
||||||
/* GUC manipulation functions */
|
/* GUC manipulation functions */
|
||||||
bool set_config(PGconn *conn, const char *config_param, const char *config_value);
|
bool set_config(PGconn *conn, const char *config_param, const char *config_value);
|
||||||
bool set_config_bool(PGconn *conn, const char *config_param, bool state);
|
bool set_config_bool(PGconn *conn, const char *config_param, bool state);
|
||||||
int guc_set(PGconn *conn, const char *parameter, const char *op,
|
int guc_set(PGconn *conn, const char *parameter, const char *op, const char *value);
|
||||||
const char *value);
|
int guc_set_typed(PGconn *conn, const char *parameter, const char *op, const char *value, const char *datatype);
|
||||||
int guc_set_typed(PGconn *conn, const char *parameter, const char *op,
|
|
||||||
const char *value, const char *datatype);
|
|
||||||
bool get_pg_setting(PGconn *conn, const char *setting, char *output);
|
bool get_pg_setting(PGconn *conn, const char *setting, char *output);
|
||||||
|
bool alter_system_int(PGconn *conn, const char *name, int value);
|
||||||
|
bool pg_reload_conf(PGconn *conn);
|
||||||
|
|
||||||
/* server information functions */
|
/* server information functions */
|
||||||
bool get_cluster_size(PGconn *conn, char *size);
|
bool get_cluster_size(PGconn *conn, char *size);
|
||||||
int get_server_version(PGconn *conn, char *server_version);
|
int get_server_version(PGconn *conn, char *server_version_buf);
|
||||||
|
|
||||||
RecoveryType get_recovery_type(PGconn *conn);
|
RecoveryType get_recovery_type(PGconn *conn);
|
||||||
int get_primary_node_id(PGconn *conn);
|
int get_primary_node_id(PGconn *conn);
|
||||||
bool can_use_pg_rewind(PGconn *conn, const char *data_directory, PQExpBufferData *reason);
|
|
||||||
int get_ready_archive_files(PGconn *conn, const char *data_directory);
|
int get_ready_archive_files(PGconn *conn, const char *data_directory);
|
||||||
bool identify_system(PGconn *repl_conn, t_system_identification *identification);
|
bool identify_system(PGconn *repl_conn, t_system_identification *identification);
|
||||||
|
TimeLineHistoryEntry *get_timeline_history(PGconn *repl_conn, TimeLineID tli);
|
||||||
|
|
||||||
|
/* repmgrd shared memory functions */
|
||||||
bool repmgrd_set_local_node_id(PGconn *conn, int local_node_id);
|
bool repmgrd_set_local_node_id(PGconn *conn, int local_node_id);
|
||||||
|
int repmgrd_get_local_node_id(PGconn *conn);
|
||||||
|
bool repmgrd_check_local_node_id(PGconn *conn);
|
||||||
|
BackupState server_in_exclusive_backup_mode(PGconn *conn);
|
||||||
|
void repmgrd_set_pid(PGconn *conn, pid_t repmgrd_pid, const char *pidfile);
|
||||||
|
pid_t repmgrd_get_pid(PGconn *conn);
|
||||||
|
bool repmgrd_is_running(PGconn *conn);
|
||||||
|
bool repmgrd_is_paused(PGconn *conn);
|
||||||
|
bool repmgrd_pause(PGconn *conn, bool pause);
|
||||||
|
pid_t get_wal_receiver_pid(PGconn *conn);
|
||||||
|
|
||||||
/* extension functions */
|
/* extension functions */
|
||||||
ExtensionStatus get_repmgr_extension_status(PGconn *conn);
|
ExtensionStatus get_repmgr_extension_status(PGconn *conn, t_extension_versions *extversions);
|
||||||
|
|
||||||
/* node management functions */
|
/* node management functions */
|
||||||
void checkpoint(PGconn *conn);
|
void checkpoint(PGconn *conn);
|
||||||
bool vacuum_table(PGconn *conn, const char *table);
|
bool vacuum_table(PGconn *conn, const char *table);
|
||||||
|
bool promote_standby(PGconn *conn, bool wait, int wait_seconds);
|
||||||
|
bool resume_wal_replay(PGconn *conn);
|
||||||
|
|
||||||
/* node record functions */
|
/* node record functions */
|
||||||
t_server_type parse_node_type(const char *type);
|
t_server_type parse_node_type(const char *type);
|
||||||
const char *get_node_type_string(t_server_type type);
|
const char *get_node_type_string(t_server_type type);
|
||||||
|
|
||||||
RecordStatus get_node_record(PGconn *conn, int node_id, t_node_info *node_info);
|
RecordStatus get_node_record(PGconn *conn, int node_id, t_node_info *node_info);
|
||||||
|
RecordStatus refresh_node_record(PGconn *conn, int node_id, t_node_info *node_info);
|
||||||
|
|
||||||
|
RecordStatus get_node_record_with_upstream(PGconn *conn, int node_id, t_node_info *node_info);
|
||||||
|
|
||||||
RecordStatus get_node_record_by_name(PGconn *conn, const char *node_name, t_node_info *node_info);
|
RecordStatus get_node_record_by_name(PGconn *conn, const char *node_name, t_node_info *node_info);
|
||||||
t_node_info *get_node_record_pointer(PGconn *conn, int node_id);
|
t_node_info *get_node_record_pointer(PGconn *conn, int node_id);
|
||||||
|
|
||||||
bool get_local_node_record(PGconn *conn, int node_id, t_node_info *node_info);
|
bool get_local_node_record(PGconn *conn, int node_id, t_node_info *node_info);
|
||||||
bool get_primary_node_record(PGconn *conn, t_node_info *node_info);
|
bool get_primary_node_record(PGconn *conn, t_node_info *node_info);
|
||||||
|
|
||||||
void get_all_node_records(PGconn *conn, NodeInfoList *node_list);
|
bool get_all_node_records(PGconn *conn, NodeInfoList *node_list);
|
||||||
void get_downstream_node_records(PGconn *conn, int node_id, NodeInfoList *nodes);
|
void get_downstream_node_records(PGconn *conn, int node_id, NodeInfoList *nodes);
|
||||||
void get_active_sibling_node_records(PGconn *conn, int node_id, int upstream_node_id, NodeInfoList *node_list);
|
void get_active_sibling_node_records(PGconn *conn, int node_id, int upstream_node_id, NodeInfoList *node_list);
|
||||||
void get_node_records_by_priority(PGconn *conn, NodeInfoList *node_list);
|
void get_node_records_by_priority(PGconn *conn, NodeInfoList *node_list);
|
||||||
void get_all_node_records_with_upstream(PGconn *conn, NodeInfoList *node_list);
|
bool get_all_node_records_with_upstream(PGconn *conn, NodeInfoList *node_list);
|
||||||
|
bool get_downstream_nodes_with_missing_slot(PGconn *conn, int this_node_id, NodeInfoList *noede_list);
|
||||||
|
|
||||||
bool create_node_record(PGconn *conn, char *repmgr_action, t_node_info *node_info);
|
bool create_node_record(PGconn *conn, char *repmgr_action, t_node_info *node_info);
|
||||||
bool update_node_record(PGconn *conn, char *repmgr_action, t_node_info *node_info);
|
bool update_node_record(PGconn *conn, char *repmgr_action, t_node_info *node_info);
|
||||||
bool delete_node_record(PGconn *conn, int node);
|
bool delete_node_record(PGconn *conn, int node);
|
||||||
|
bool truncate_node_records(PGconn *conn);
|
||||||
|
|
||||||
bool update_node_record_set_active(PGconn *conn, int this_node_id, bool active);
|
bool update_node_record_set_active(PGconn *conn, int this_node_id, bool active);
|
||||||
bool update_node_record_set_primary(PGconn *conn, int this_node_id);
|
bool update_node_record_set_primary(PGconn *conn, int this_node_id);
|
||||||
|
bool update_node_record_set_active_standby(PGconn *conn, int this_node_id);
|
||||||
bool update_node_record_set_upstream(PGconn *conn, int this_node_id, int new_upstream_node_id);
|
bool update_node_record_set_upstream(PGconn *conn, int this_node_id, int new_upstream_node_id);
|
||||||
bool update_node_record_status(PGconn *conn, int this_node_id, char *type, int upstream_node_id, bool active);
|
bool update_node_record_status(PGconn *conn, int this_node_id, char *type, int upstream_node_id, bool active);
|
||||||
bool update_node_record_conn_priority(PGconn *conn, t_configuration_options *options);
|
bool update_node_record_conn_priority(PGconn *conn, t_configuration_options *options);
|
||||||
|
bool update_node_record_slot_name(PGconn *primary_conn, int node_id, char *slot_name);
|
||||||
|
|
||||||
|
bool witness_copy_node_records(PGconn *primary_conn, PGconn *witness_conn);
|
||||||
|
|
||||||
void clear_node_info_list(NodeInfoList *nodes);
|
void clear_node_info_list(NodeInfoList *nodes);
|
||||||
|
|
||||||
@@ -438,21 +499,29 @@ void config_file_list_add(t_configfile_list *list, const char *file, const char
|
|||||||
bool create_event_record(PGconn *conn, t_configuration_options *options, int node_id, char *event, bool successful, char *details);
|
bool create_event_record(PGconn *conn, t_configuration_options *options, int node_id, char *event, bool successful, char *details);
|
||||||
bool create_event_notification(PGconn *conn, t_configuration_options *options, int node_id, char *event, bool successful, char *details);
|
bool create_event_notification(PGconn *conn, t_configuration_options *options, int node_id, char *event, bool successful, char *details);
|
||||||
bool create_event_notification_extended(PGconn *conn, t_configuration_options *options, int node_id, char *event, bool successful, char *details, t_event_info *event_info);
|
bool create_event_notification_extended(PGconn *conn, t_configuration_options *options, int node_id, char *event, bool successful, char *details, t_event_info *event_info);
|
||||||
|
PGresult *get_event_records(PGconn *conn, int node_id, const char *node_name, const char *event, bool all, int limit);
|
||||||
|
|
||||||
/* replication slot functions */
|
/* replication slot functions */
|
||||||
bool create_replication_slot(PGconn *conn, char *slot_name, int server_version_num, PQExpBufferData *error_msg);
|
void create_slot_name(char *slot_name, int node_id);
|
||||||
|
bool create_replication_slot(PGconn *conn, char *slot_name, PQExpBufferData *error_msg);
|
||||||
bool drop_replication_slot(PGconn *conn, char *slot_name);
|
bool drop_replication_slot(PGconn *conn, char *slot_name);
|
||||||
RecordStatus get_slot_record(PGconn *conn, char *slot_name, t_replication_slot *record);
|
RecordStatus get_slot_record(PGconn *conn, char *slot_name, t_replication_slot *record);
|
||||||
|
int get_free_replication_slot_count(PGconn *conn);
|
||||||
|
int get_inactive_replication_slots(PGconn *conn, KeyValueList *list);
|
||||||
|
|
||||||
/* tablespace functions */
|
/* tablespace functions */
|
||||||
bool get_tablespace_name_by_location(PGconn *conn, const char *location, char *name);
|
bool get_tablespace_name_by_location(PGconn *conn, const char *location, char *name);
|
||||||
|
|
||||||
/* asynchronous query functions */
|
/* asynchronous query functions */
|
||||||
bool cancel_query(PGconn *conn, int timeout);
|
bool cancel_query(PGconn *conn, int timeout);
|
||||||
int wait_connection_availability(PGconn *conn, long long timeout);
|
int wait_connection_availability(PGconn *conn, int timeout);
|
||||||
|
|
||||||
/* node availability functions */
|
/* node availability functions */
|
||||||
bool is_server_available(const char *conninfo);
|
bool is_server_available(const char *conninfo);
|
||||||
|
bool is_server_available_quiet(const char *conninfo);
|
||||||
|
bool is_server_available_params(t_conninfo_param_list *param_list);
|
||||||
|
ExecStatusType connection_ping(PGconn *conn);
|
||||||
|
ExecStatusType connection_ping_reconnect(PGconn *conn);
|
||||||
|
|
||||||
/* monitoring functions */
|
/* monitoring functions */
|
||||||
void
|
void
|
||||||
@@ -468,43 +537,56 @@ add_monitoring_record(PGconn *primary_conn,
|
|||||||
long long unsigned int apply_lag_bytes
|
long long unsigned int apply_lag_bytes
|
||||||
);
|
);
|
||||||
|
|
||||||
int get_number_of_monitoring_records_to_delete(PGconn *primary_conn, int keep_history);
|
int get_number_of_monitoring_records_to_delete(PGconn *primary_conn, int keep_history, int node_id);
|
||||||
bool delete_monitoring_records(PGconn *primary_conn, int keep_history);
|
bool delete_monitoring_records(PGconn *primary_conn, int keep_history, int node_id);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* node voting functions */
|
/* node voting functions */
|
||||||
NodeVotingStatus get_voting_status(PGconn *conn);
|
void initialize_voting_term(PGconn *conn);
|
||||||
VoteRequestResult request_vote(PGconn *conn, t_node_info *this_node, t_node_info *other_node, int electoral_term);
|
int get_current_term(PGconn *conn);
|
||||||
int set_voting_status_initiated(PGconn *conn);
|
void increment_current_term(PGconn *conn);
|
||||||
bool announce_candidature(PGconn *conn, t_node_info *this_node, t_node_info *other_node, int electoral_term);
|
bool announce_candidature(PGconn *conn, t_node_info *this_node, t_node_info *other_node, int electoral_term);
|
||||||
void notify_follow_primary(PGconn *conn, int primary_node_id);
|
void notify_follow_primary(PGconn *conn, int primary_node_id);
|
||||||
bool get_new_primary(PGconn *conn, int *primary_node_id);
|
bool get_new_primary(PGconn *conn, int *primary_node_id);
|
||||||
void reset_voting_status(PGconn *conn);
|
void reset_voting_status(PGconn *conn);
|
||||||
|
|
||||||
/* replication status functions */
|
/* replication status functions */
|
||||||
XLogRecPtr get_current_wal_lsn(PGconn *conn);
|
XLogRecPtr get_primary_current_lsn(PGconn *conn);
|
||||||
|
XLogRecPtr get_node_current_lsn(PGconn *conn);
|
||||||
XLogRecPtr get_last_wal_receive_location(PGconn *conn);
|
XLogRecPtr get_last_wal_receive_location(PGconn *conn);
|
||||||
bool get_replication_info(PGconn *conn, ReplInfo *replication_info);
|
void init_replication_info(ReplInfo *replication_info);
|
||||||
|
bool get_replication_info(PGconn *conn, t_server_type node_type, ReplInfo *replication_info);
|
||||||
int get_replication_lag_seconds(PGconn *conn);
|
int get_replication_lag_seconds(PGconn *conn);
|
||||||
void get_node_replication_stats(PGconn *conn, t_node_info *node_info);
|
void get_node_replication_stats(PGconn *conn, t_node_info *node_info);
|
||||||
bool is_downstream_node_attached(PGconn *conn, char *node_name);
|
bool is_downstream_node_attached(PGconn *conn, char *node_name);
|
||||||
|
void set_upstream_last_seen(PGconn *conn);
|
||||||
|
int get_upstream_last_seen(PGconn *conn, t_server_type node_type);
|
||||||
|
bool is_wal_replay_paused(PGconn *conn, bool check_pending_wal);
|
||||||
|
|
||||||
/* BDR functions */
|
/* BDR functions */
|
||||||
|
int get_bdr_version_num(void);
|
||||||
void get_all_bdr_node_records(PGconn *conn, BdrNodeInfoList *node_list);
|
void get_all_bdr_node_records(PGconn *conn, BdrNodeInfoList *node_list);
|
||||||
RecordStatus get_bdr_node_record_by_name(PGconn *conn, const char *node_name, t_bdr_node_info *node_info);
|
RecordStatus get_bdr_node_record_by_name(PGconn *conn, const char *node_name, t_bdr_node_info *node_info);
|
||||||
bool is_bdr_db(PGconn *conn, PQExpBufferData *output);
|
bool is_bdr_db(PGconn *conn, PQExpBufferData *output);
|
||||||
|
bool is_bdr_db_quiet(PGconn *conn);
|
||||||
bool is_active_bdr_node(PGconn *conn, const char *node_name);
|
bool is_active_bdr_node(PGconn *conn, const char *node_name);
|
||||||
bool is_bdr_repmgr(PGconn *conn);
|
bool is_bdr_repmgr(PGconn *conn);
|
||||||
|
char *get_default_bdr_replication_set(PGconn *conn);
|
||||||
bool is_table_in_bdr_replication_set(PGconn *conn, const char *tablename, const char *set);
|
bool is_table_in_bdr_replication_set(PGconn *conn, const char *tablename, const char *set);
|
||||||
bool add_table_to_bdr_replication_set(PGconn *conn, const char *tablename, const char *set);
|
bool add_table_to_bdr_replication_set(PGconn *conn, const char *tablename, const char *set);
|
||||||
void add_extension_tables_to_bdr_replication_set(PGconn *conn);
|
void add_extension_tables_to_bdr_replication_set(PGconn *conn);
|
||||||
|
bool bdr_node_name_matches(PGconn *conn, const char *node_name, PQExpBufferData *bdr_local_node_name);
|
||||||
bool bdr_node_exists(PGconn *conn, const char *node_name);
|
|
||||||
ReplSlotStatus get_bdr_node_replication_slot_status(PGconn *conn, const char *node_name);
|
ReplSlotStatus get_bdr_node_replication_slot_status(PGconn *conn, const char *node_name);
|
||||||
void get_bdr_other_node_name(PGconn *conn, int node_id, char *name_buf);
|
void get_bdr_other_node_name(PGconn *conn, int node_id, char *name_buf);
|
||||||
|
|
||||||
bool am_bdr_failover_handler(PGconn *conn, int node_id);
|
bool am_bdr_failover_handler(PGconn *conn, int node_id);
|
||||||
void unset_bdr_failover_handler(PGconn *conn);
|
void unset_bdr_failover_handler(PGconn *conn);
|
||||||
|
bool bdr_node_has_repmgr_set(PGconn *conn, const char *node_name);
|
||||||
|
bool bdr_node_set_repmgr_set(PGconn *conn, const char *node_name);
|
||||||
|
|
||||||
|
/* miscellaneous debugging functions */
|
||||||
|
const char *print_node_status(NodeStatus node_status);
|
||||||
|
const char *print_pqping_status(PGPing ping_status);
|
||||||
|
|
||||||
#endif /* _REPMGR_DBUTILS_H_ */
|
#endif /* _REPMGR_DBUTILS_H_ */
|
||||||
|
|||||||
251
dirutil.c
251
dirutil.c
@@ -3,7 +3,7 @@
|
|||||||
* dirmod.c
|
* dirmod.c
|
||||||
* directory handling functions
|
* directory handling functions
|
||||||
*
|
*
|
||||||
* Copyright (c) 2ndQuadrant, 2010-2017
|
* Copyright (c) 2ndQuadrant, 2010-2019
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
|
#include <signal.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@@ -34,34 +35,33 @@
|
|||||||
#include "dirutil.h"
|
#include "dirutil.h"
|
||||||
#include "strutil.h"
|
#include "strutil.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
#include "controldata.h"
|
||||||
|
|
||||||
static int unlink_dir_callback(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf);
|
static int unlink_dir_callback(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf);
|
||||||
|
|
||||||
|
/* PID can be negative if backend is standalone */
|
||||||
|
typedef long pgpid_t;
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* make sure the directory either doesn't exist or is empty
|
* Check if a directory exists, and if so whether it is empty.
|
||||||
* we use this function to check the new data directory and
|
|
||||||
* the directories for tablespaces
|
|
||||||
*
|
*
|
||||||
* This is the same check initdb does on the new PGDATA dir
|
* This function is used for checking both the data directory
|
||||||
*
|
* and tablespace directories.
|
||||||
* Returns 0 if nonexistent, 1 if exists and empty, 2 if not empty,
|
|
||||||
* or -1 if trouble accessing directory
|
|
||||||
*/
|
*/
|
||||||
int
|
DataDirState
|
||||||
check_dir(char *path)
|
check_dir(const char *path)
|
||||||
{
|
{
|
||||||
DIR *chkdir;
|
DIR *chkdir = NULL;
|
||||||
struct dirent *file;
|
struct dirent *file = NULL;
|
||||||
int result = 1;
|
int result = DIR_EMPTY;
|
||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
|
|
||||||
chkdir = opendir(path);
|
chkdir = opendir(path);
|
||||||
|
|
||||||
if (!chkdir)
|
if (!chkdir)
|
||||||
return (errno == ENOENT) ? 0 : -1;
|
return (errno == ENOENT) ? DIR_NOENT : DIR_ERROR;
|
||||||
|
|
||||||
while ((file = readdir(chkdir)) != NULL)
|
while ((file = readdir(chkdir)) != NULL)
|
||||||
{
|
{
|
||||||
@@ -73,25 +73,15 @@ check_dir(char *path)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
result = 2; /* not empty */
|
result = DIR_NOT_EMPTY;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WIN32
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This fix is in mingw cvs (runtime/mingwex/dirent.c rev 1.4), but not in
|
|
||||||
* released version
|
|
||||||
*/
|
|
||||||
if (GetLastError() == ERROR_NO_MORE_FILES)
|
|
||||||
errno = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
closedir(chkdir);
|
closedir(chkdir);
|
||||||
|
|
||||||
if (errno != 0)
|
if (errno != 0)
|
||||||
return -1; /* some kind of I/O error? */
|
return DIR_ERROR; /* some kind of I/O error? */
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -101,25 +91,30 @@ check_dir(char *path)
|
|||||||
* Create directory with error log message when failing
|
* Create directory with error log message when failing
|
||||||
*/
|
*/
|
||||||
bool
|
bool
|
||||||
create_dir(char *path)
|
create_dir(const char *path)
|
||||||
{
|
{
|
||||||
if (mkdir_p(path, 0700) == 0)
|
char create_dir_path[MAXPGPATH];
|
||||||
|
|
||||||
|
/* mkdir_p() may modify the supplied path */
|
||||||
|
strncpy(create_dir_path, path, MAXPGPATH);
|
||||||
|
|
||||||
|
if (mkdir_p(create_dir_path, 0700) == 0)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
log_error(_("unable to create directory \"%s\": %s"),
|
log_error(_("unable to create directory \"%s\""), create_dir_path);
|
||||||
path, strerror(errno));
|
log_detail("%s", strerror(errno));
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
set_dir_permissions(char *path)
|
set_dir_permissions(const char *path)
|
||||||
{
|
{
|
||||||
return (chmod(path, 0700) != 0) ? false : true;
|
return (chmod(path, 0700) != 0) ? false : true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* function from initdb.c */
|
/* function from initdb.c */
|
||||||
/* source adapted from FreeBSD /src/bin/mkdir/mkdir.c */
|
/* source adapted from FreeBSD /src/bin/mkdir/mkdir.c */
|
||||||
|
|
||||||
@@ -146,26 +141,6 @@ mkdir_p(char *path, mode_t omode)
|
|||||||
oumask = 0;
|
oumask = 0;
|
||||||
retval = 0;
|
retval = 0;
|
||||||
|
|
||||||
#ifdef WIN32
|
|
||||||
/* skip network and drive specifiers for win32 */
|
|
||||||
if (strlen(p) >= 2)
|
|
||||||
{
|
|
||||||
if (p[0] == '/' && p[1] == '/')
|
|
||||||
{
|
|
||||||
/* network drive */
|
|
||||||
p = strstr(p + 2, "/");
|
|
||||||
if (p == NULL)
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
else if (p[1] == ':' &&
|
|
||||||
((p[0] >= 'a' && p[0] <= 'z') ||
|
|
||||||
(p[0] >= 'A' && p[0] <= 'Z')))
|
|
||||||
{
|
|
||||||
/* local drive */
|
|
||||||
p += 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (p[0] == '/') /* Skip leading '/'. */
|
if (p[0] == '/') /* Skip leading '/'. */
|
||||||
++p;
|
++p;
|
||||||
@@ -227,9 +202,9 @@ mkdir_p(char *path, mode_t omode)
|
|||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
is_pg_dir(char *path)
|
is_pg_dir(const char *path)
|
||||||
{
|
{
|
||||||
char dirpath[MAXPGPATH];
|
char dirpath[MAXPGPATH] = "";
|
||||||
struct stat sb;
|
struct stat sb;
|
||||||
|
|
||||||
/* test pgdata */
|
/* test pgdata */
|
||||||
@@ -242,17 +217,93 @@ is_pg_dir(char *path)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Attempt to determine if a PostgreSQL data directory is in use
|
||||||
|
* by reading the pidfile. This is the same mechanism used by
|
||||||
|
* "pg_ctl".
|
||||||
|
*
|
||||||
|
* This function will abort with appropriate log messages if a file error
|
||||||
|
* is encountered, as the user will need to address the situation before
|
||||||
|
* any further useful progress can be made.
|
||||||
|
*/
|
||||||
|
PgDirState
|
||||||
|
is_pg_running(const char *path)
|
||||||
|
{
|
||||||
|
long pid;
|
||||||
|
FILE *pidf;
|
||||||
|
|
||||||
|
char pid_file[MAXPGPATH];
|
||||||
|
|
||||||
|
/* it's reasonable to assume the pidfile name will not change */
|
||||||
|
snprintf(pid_file, MAXPGPATH, "%s/postmaster.pid", path);
|
||||||
|
|
||||||
|
pidf = fopen(pid_file, "r");
|
||||||
|
if (pidf == NULL)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* No PID file - PostgreSQL shouldn't be running. From 9.3 (the
|
||||||
|
* earliesty version we care about) removal of the PID file will
|
||||||
|
* cause the postmaster to shut down, so it's highly unlikely
|
||||||
|
* that PostgreSQL will still be running.
|
||||||
|
*/
|
||||||
|
if (errno == ENOENT)
|
||||||
|
{
|
||||||
|
return PG_DIR_NOT_RUNNING;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
log_error(_("unable to open PostgreSQL PID file \"%s\""), pid_file);
|
||||||
|
log_detail("%s", strerror(errno));
|
||||||
|
exit(ERR_BAD_CONFIG);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* In the unlikely event we're unable to extract a PID from the PID file,
|
||||||
|
* log a warning but assume we're not dealing with a running instance
|
||||||
|
* as PostgreSQL should have shut itself down in these cases anyway.
|
||||||
|
*/
|
||||||
|
if (fscanf(pidf, "%ld", &pid) != 1)
|
||||||
|
{
|
||||||
|
/* Is the file empty? */
|
||||||
|
if (ftell(pidf) == 0 && feof(pidf))
|
||||||
|
{
|
||||||
|
log_warning(_("PostgreSQL PID file \"%s\" is empty"), path);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
log_warning(_("invalid data in PostgreSQL PID file \"%s\""), path);
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(pidf);
|
||||||
|
|
||||||
|
return PG_DIR_NOT_RUNNING;
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(pidf);
|
||||||
|
|
||||||
|
if (pid == getpid())
|
||||||
|
return PG_DIR_NOT_RUNNING;
|
||||||
|
|
||||||
|
if (pid == getppid())
|
||||||
|
return PG_DIR_NOT_RUNNING;
|
||||||
|
|
||||||
|
if (kill(pid, 0) == 0)
|
||||||
|
return PG_DIR_RUNNING;
|
||||||
|
|
||||||
|
return PG_DIR_NOT_RUNNING;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
create_pg_dir(char *path, bool force)
|
create_pg_dir(const char *path, bool force)
|
||||||
{
|
{
|
||||||
bool pg_dir = false;
|
/* Check this directory can be used as a PGDATA dir */
|
||||||
|
|
||||||
/* Check this directory could be used as a PGDATA dir */
|
|
||||||
switch (check_dir(path))
|
switch (check_dir(path))
|
||||||
{
|
{
|
||||||
case 0:
|
case DIR_NOENT:
|
||||||
/* dir not there, must create it */
|
/* directory does not exist, attempt to create it */
|
||||||
log_info(_("creating directory \"%s\"..."), path);
|
log_info(_("creating directory \"%s\"..."), path);
|
||||||
|
|
||||||
if (!create_dir(path))
|
if (!create_dir(path))
|
||||||
@@ -262,55 +313,81 @@ create_pg_dir(char *path, bool force)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 1:
|
case DIR_EMPTY:
|
||||||
/* Present but empty, fix permissions and use it */
|
/* exists but empty, fix permissions and use it */
|
||||||
log_info(_("checking and correcting permissions on existing directory %s"),
|
log_info(_("checking and correcting permissions on existing directory \"%s\""),
|
||||||
path);
|
path);
|
||||||
|
|
||||||
if (!set_dir_permissions(path))
|
if (!set_dir_permissions(path))
|
||||||
{
|
{
|
||||||
log_error(_("unable to change permissions of directory \"%s\":\n %s"),
|
log_error(_("unable to change permissions of directory \"%s\""), path);
|
||||||
path, strerror(errno));
|
log_detail("%s", strerror(errno));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 2:
|
case DIR_NOT_EMPTY:
|
||||||
/* Present and not empty */
|
/* exists but is not empty */
|
||||||
log_warning(_("directory \"%s\" exists but is not empty"),
|
log_warning(_("directory \"%s\" exists but is not empty"),
|
||||||
path);
|
path);
|
||||||
|
|
||||||
pg_dir = is_pg_dir(path);
|
if (is_pg_dir(path))
|
||||||
|
|
||||||
if (pg_dir && force)
|
|
||||||
{
|
{
|
||||||
/* TODO: check DB state, if not running overwrite */
|
if (force == true)
|
||||||
|
|
||||||
if (false)
|
|
||||||
{
|
{
|
||||||
log_notice(_("deleting existing data directory \"%s\""), path);
|
log_notice(_("-F/--force provided - deleting existing data directory \"%s\""), path);
|
||||||
nftw(path, unlink_dir_callback, 64, FTW_DEPTH | FTW_PHYS);
|
nftw(path, unlink_dir_callback, 64, FTW_DEPTH | FTW_PHYS);
|
||||||
|
|
||||||
|
/* recreate the directory ourselves to ensure permissions are correct */
|
||||||
|
if (!create_dir(path))
|
||||||
|
{
|
||||||
|
log_error(_("unable to create directory \"%s\"..."),
|
||||||
|
path);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
/* Let it continue */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else if (pg_dir && !force)
|
|
||||||
{
|
|
||||||
log_hint(_("This looks like a PostgreSQL directory.\n"
|
|
||||||
"If you are sure you want to clone here, "
|
|
||||||
"please check there is no PostgreSQL server "
|
|
||||||
"running and use the -F/--force option"));
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (force == true)
|
||||||
|
{
|
||||||
|
log_notice(_("deleting existing directory \"%s\""), path);
|
||||||
|
nftw(path, unlink_dir_callback, 64, FTW_DEPTH | FTW_PHYS);
|
||||||
|
|
||||||
return false;
|
/* recreate the directory ourselves to ensure permissions are correct */
|
||||||
default:
|
if (!create_dir(path))
|
||||||
log_error(_("could not access directory \"%s\": %s"),
|
{
|
||||||
path, strerror(errno));
|
log_error(_("unable to create directory \"%s\"..."),
|
||||||
|
path);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DIR_ERROR:
|
||||||
|
log_error(_("could not access directory \"%s\"")
|
||||||
|
, path);
|
||||||
|
log_detail("%s", strerror(errno));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
rmdir_recursive(const char *path)
|
||||||
|
{
|
||||||
|
return nftw(path, unlink_dir_callback, 64, FTW_DEPTH | FTW_PHYS);
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
unlink_dir_callback(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf)
|
unlink_dir_callback(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf)
|
||||||
{
|
{
|
||||||
|
|||||||
31
dirutil.h
31
dirutil.h
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* dirutil.h
|
* dirutil.h
|
||||||
* Copyright (c) 2ndQuadrant, 2010-2017
|
* Copyright (c) 2ndQuadrant, 2010-2019
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -19,12 +19,29 @@
|
|||||||
#ifndef _DIRUTIL_H_
|
#ifndef _DIRUTIL_H_
|
||||||
#define _DIRUTIL_H_
|
#define _DIRUTIL_H_
|
||||||
|
|
||||||
extern int mkdir_p(char *path, mode_t omode);
|
typedef enum
|
||||||
extern bool set_dir_permissions(char *path);
|
{
|
||||||
|
DIR_ERROR = -1,
|
||||||
|
DIR_NOENT,
|
||||||
|
DIR_EMPTY,
|
||||||
|
DIR_NOT_EMPTY
|
||||||
|
} DataDirState;
|
||||||
|
|
||||||
extern int check_dir(char *path);
|
typedef enum
|
||||||
extern bool create_dir(char *path);
|
{
|
||||||
extern bool is_pg_dir(char *path);
|
PG_DIR_ERROR = -1,
|
||||||
extern bool create_pg_dir(char *path, bool force);
|
PG_DIR_NOT_RUNNING,
|
||||||
|
PG_DIR_RUNNING
|
||||||
|
} PgDirState;
|
||||||
|
|
||||||
|
extern int mkdir_p(char *path, mode_t omode);
|
||||||
|
extern bool set_dir_permissions(const char *path);
|
||||||
|
|
||||||
|
extern DataDirState check_dir(const char *path);
|
||||||
|
extern bool create_dir(const char *path);
|
||||||
|
extern bool is_pg_dir(const char *path);
|
||||||
|
extern PgDirState is_pg_running(const char *path);
|
||||||
|
extern bool create_pg_dir(const char *path, bool force);
|
||||||
|
extern int rmdir_recursive(const char *path);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
7
doc/.gitignore
vendored
Normal file
7
doc/.gitignore
vendored
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
HTML.index
|
||||||
|
bookindex.sgml
|
||||||
|
html-stamp
|
||||||
|
html/
|
||||||
|
nochunks.dsl
|
||||||
|
repmgr.html
|
||||||
|
version.sgml
|
||||||
76
doc/Makefile.in
Normal file
76
doc/Makefile.in
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
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) -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) -d stylesheet.dsl -i include-index $<
|
||||||
|
cp $(srcdir)/stylesheet.css $(srcdir)/website-docs.css html/
|
||||||
|
touch $@
|
||||||
|
|
||||||
|
repmgr.html: repmgr.sgml $(ALLSGML) $(GENERATED_SGML) stylesheet.dsl website-docs.css
|
||||||
|
sed '/html-index-filename/a\
|
||||||
|
(define nochunks #t)' <stylesheet.dsl >nochunks.dsl
|
||||||
|
$(JADE.html.call) -d nochunks.dsl -i include-index $< >repmgr.html
|
||||||
|
|
||||||
|
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) -d stylesheet.dsl -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 -f 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
|
||||||
438
doc/appendix-faq.sgml
Normal file
438
doc/appendix-faq.sgml
Normal file
@@ -0,0 +1,438 @@
|
|||||||
|
<appendix id="appendix-faq" xreflabel="FAQ">
|
||||||
|
<indexterm>
|
||||||
|
<primary>FAQ (Frequently Asked Questions)</primary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<title>FAQ (Frequently Asked Questions)</title>
|
||||||
|
|
||||||
|
<sect1 id="faq-general" xreflabel="General">
|
||||||
|
<title>General</title>
|
||||||
|
|
||||||
|
<sect2 id="faq-xrepmgr-version-diff" xreflabel="Version differences">
|
||||||
|
<title>What's the difference between the repmgr versions?</title>
|
||||||
|
<para>
|
||||||
|
&repmgr; 4 is a complete rewrite of the existing &repmgr; code base
|
||||||
|
and implements &repmgr; as a PostgreSQL extension. It
|
||||||
|
supports all PostgreSQL versions from 9.3 (although some &repmgr;
|
||||||
|
features are not available for PostgreSQL 9.3 and 9.4).
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
&repmgr; 3.x builds on the improved replication facilities added
|
||||||
|
in PostgreSQL 9.3, as well as improved automated failover support
|
||||||
|
via <application>repmgrd</application>, and is not compatible with PostgreSQL 9.2
|
||||||
|
and earlier. We recommend upgrading to &repmgr; 4, as the &repmgr; 3.x
|
||||||
|
series is no longer maintained.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
&repmgr; 2.x supports PostgreSQL 9.0 ~ 9.3. While it is compatible
|
||||||
|
with PostgreSQL 9.3, we recommend using repmgr 4.x. &repmgr; 2.x is
|
||||||
|
no longer maintained.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
See also <link linkend="install-compatibility-matrix">&repmgr; compatibility matrix</link>
|
||||||
|
and <link linkend="faq-upgrade-repmgr">Should I upgrade &repmgr;?</link>.
|
||||||
|
</para>
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
<sect2 id="faq-replication-slots-advantage" xreflabel="Advantages of replication slots">
|
||||||
|
<title>What's the advantage of using replication slots?</title>
|
||||||
|
<para>
|
||||||
|
Replication slots, introduced in PostgreSQL 9.4, ensure that the
|
||||||
|
primary server will retain WAL files until they have been consumed
|
||||||
|
by all standby servers. This means standby servers should never
|
||||||
|
fail due to not being able to retrieve required WAL files from the
|
||||||
|
primary.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
However this does mean that if a standby is no longer connected to the
|
||||||
|
primary, the presence of the replication slot will cause WAL files
|
||||||
|
to be retained indefinitely, and eventually lead to disk space
|
||||||
|
exhaustion.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<tip>
|
||||||
|
<para>
|
||||||
|
2ndQuadrant's recommended configuration is to configure
|
||||||
|
<ulink url="https://www.pgbarman.org/">Barman</ulink> as a fallback
|
||||||
|
source of WAL files, rather than maintain replication slots for
|
||||||
|
each standby. See also: <link linkend="cloning-from-barman-restore-command">Using Barman as a WAL file source</link>.
|
||||||
|
</para>
|
||||||
|
</tip>
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
<sect2 id="faq-replication-slots-number" xreflabel="Number of replication slots">
|
||||||
|
<title>How many replication slots should I define in <varname>max_replication_slots</varname>?</title>
|
||||||
|
<para>
|
||||||
|
Normally at least same number as the number of standbys which will connect
|
||||||
|
to the node. Note that changes to <varname>max_replication_slots</varname> require a server
|
||||||
|
restart to take effect, and as there is no particular penalty for unused
|
||||||
|
replication slots, setting a higher figure will make adding new nodes
|
||||||
|
easier.
|
||||||
|
</para>
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
<sect2 id="faq-hash-index" xreflabel="Hash indexes">
|
||||||
|
<title>Does &repmgr; support hash indexes?</title>
|
||||||
|
<para>
|
||||||
|
Before PostgreSQL 10, hash indexes were not WAL logged and are therefore not suitable
|
||||||
|
for use in streaming replication in PostgreSQL 9.6 and earlier. See the
|
||||||
|
<ulink url="https://www.postgresql.org/docs/9.6/sql-createindex.html#AEN80279">PostgreSQL documentation</ulink>
|
||||||
|
for details.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
From PostgreSQL 10, this restriction has been lifted and hash indexes can be used
|
||||||
|
in a streaming replication cluster.
|
||||||
|
</para>
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
<sect2 id="faq-upgrades" xreflabel="Upgrading PostgreSQL with repmgr">
|
||||||
|
<title>Can &repmgr; assist with upgrading a PostgreSQL cluster?</title>
|
||||||
|
<para>
|
||||||
|
For <emphasis>minor</emphasis> version upgrades, e.g. from 9.6.7 to 9.6.8, a common
|
||||||
|
approach is to upgrade a standby to the latest version, perform a
|
||||||
|
<link linkend="performing-switchover">switchover</link> promoting it to a primary,
|
||||||
|
then upgrade the former primary.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
For <emphasis>major</emphasis> version upgrades (e.g. from PostgreSQL 9.6 to PostgreSQL 10),
|
||||||
|
the traditional approach is to "reseed" a cluster by upgrading a single
|
||||||
|
node with <ulink url="https://www.postgresql.org/docs/current/pgupgrade.html">pg_upgrade</ulink>
|
||||||
|
and recloning standbys from this.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
To minimize downtime during major upgrades from PostgreSQL 9.4 and later,
|
||||||
|
<ulink url="https://www.2ndquadrant.com/en/resources/pglogical/">pglogical</ulink>
|
||||||
|
can be used to set up a parallel cluster using the newer PostgreSQL version,
|
||||||
|
which can be kept in sync with the existing production cluster until the
|
||||||
|
new cluster is ready to be put into production.
|
||||||
|
</para>
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
<sect2 id="faq-libdir-repmgr-error">
|
||||||
|
<title>What does this error mean: <literal>ERROR: could not access file "$libdir/repmgr"</literal>?</title>
|
||||||
|
<para>
|
||||||
|
It means the &repmgr; extension code is not installed in the
|
||||||
|
PostgreSQL application directory. This typically happens when using PostgreSQL
|
||||||
|
packages provided by a third-party vendor, which often have different
|
||||||
|
filesystem layouts.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Either use PostgreSQL packages provided by the community or 2ndQuadrant; if this
|
||||||
|
is not possible, contact your vendor for assistance.
|
||||||
|
</para>
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
<sect2 id="faq-old-packages">
|
||||||
|
<title>How can I obtain old versions of &repmgr; packages?</title>
|
||||||
|
<para>
|
||||||
|
See appendix <xref linkend="packages-old-versions"> for details.
|
||||||
|
</para>
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
<sect2 id="faq-repmgr-required-for-replication">
|
||||||
|
<title>Is &repmgr; required for streaming replication?</title>
|
||||||
|
<para>
|
||||||
|
No.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
&repmgr; (together with <application>repmgrd</application>) assists with
|
||||||
|
<emphasis>managing</emphasis> replication. It does not actually perform replication, which
|
||||||
|
is part of the core PostgreSQL functionality.
|
||||||
|
</para>
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
<sect2 id="faq-what-if-repmgr-uninstalled">
|
||||||
|
<title>Will replication stop working if &repmgr; is uninstalled?</title>
|
||||||
|
<para>
|
||||||
|
No. See preceding question.
|
||||||
|
</para>
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
<sect2 id="faq-version-mix">
|
||||||
|
<title>Does it matter if different &repmgr; versions are present in the replication cluster?</title>
|
||||||
|
<para>
|
||||||
|
Yes. If different "major" &repmgr; versions (e.g. 3.3.x and 4.1.x) are present,
|
||||||
|
&repmgr; (in particular <application>repmgrd</application>)
|
||||||
|
may not run, or run properly, or in the worst case (if different <application>repmgrd</application>
|
||||||
|
versions are running and there are differences in the failover implementation) break
|
||||||
|
your replication cluster.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
If different "minor" &repmgr; versions (e.g. 4.1.1 and 4.1.6) are installed,
|
||||||
|
&repmgr; will function, but we strongly recommend always running the same version
|
||||||
|
to ensure there are no unexpected suprises, e.g. a newer version behaving slightly
|
||||||
|
differently to the older version.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
See also <link linkend="faq-upgrade-repmgr">Should I upgrade &repmgr;?</link>.
|
||||||
|
</para>
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
<sect2 id="faq-upgrade-repmgr">
|
||||||
|
<title>Should I upgrade &repmgr;?</title>
|
||||||
|
<para>
|
||||||
|
Yes.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
We don't release new versions for fun, you know. Upgrading may require a little effort,
|
||||||
|
but running an older &repmgr; version with bugs which have since been fixed may end up
|
||||||
|
costing you more effort. The same applies to PostgreSQL itself.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
<sect2 id="faq-repmgr-conf-data-directory">
|
||||||
|
<title>Why do I need to specify the data directory location in repmgr.conf?</title>
|
||||||
|
<para>
|
||||||
|
In some circumstances &repmgr; may need to access a PostgreSQL data
|
||||||
|
directory while the PostgreSQL server is not running, e.g. to confirm
|
||||||
|
it shut down cleanly during a <link linkend="performing-switchover">switchover</link>.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Additionally, this provides support when using &repmgr; on PostgreSQL 9.6 and
|
||||||
|
earlier, where the <literal>repmgr</literal> user is not a superuser; in that
|
||||||
|
case the <literal>repmgr</literal> user will not be able to access the
|
||||||
|
<literal>data_directory</literal> configuration setting, access to which is restricted
|
||||||
|
to superusers. (In PostgreSQL 10 and later, non-superusers can be added to the
|
||||||
|
group <option>pg_read_all_settings</option> which will enable them to read this setting).
|
||||||
|
</para>
|
||||||
|
</sect2>
|
||||||
|
</sect1>
|
||||||
|
|
||||||
|
<sect1 id="faq-repmgr" xreflabel="repmgr">
|
||||||
|
<title><command>repmgr</command></title>
|
||||||
|
|
||||||
|
<sect2 id="faq-register-existing-node" xreflabel="registering an existing node">
|
||||||
|
<title>Can I register an existing PostgreSQL server with repmgr?</title>
|
||||||
|
<para>
|
||||||
|
Yes, any existing PostgreSQL server which is part of the same replication
|
||||||
|
cluster can be registered with &repmgr;. There's no requirement for a
|
||||||
|
standby to have been cloned using &repmgr;.
|
||||||
|
</para>
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
<sect2 id="faq-repmgr-clone-other-source" >
|
||||||
|
<title>Can I use a standby not cloned by &repmgr; as a &repmgr; node?</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
For a standby which has been manually cloned or recovered from an external
|
||||||
|
backup manager such as Barman, the command
|
||||||
|
<command><link linkend="repmgr-standby-clone">repmgr standby clone --recovery-conf-only</link></command>
|
||||||
|
can be used to create the correct <filename>recovery.conf</filename> file for
|
||||||
|
use with &repmgr; (and will create a replication slot if required). Once this has been done,
|
||||||
|
<link linkend="repmgr-standby-register">register the node</link> as usual.
|
||||||
|
</para>
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
<sect2 id="faq-repmgr-recovery-conf" >
|
||||||
|
<title>What does &repmgr; write in <filename>recovery.conf</filename>, and what options can be set there?</title>
|
||||||
|
<para>
|
||||||
|
See section <link linkend="repmgr-standby-clone-recovery-conf">Customising recovery.conf</link>.
|
||||||
|
</para>
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
<sect2 id="faq-repmgr-failed-primary-standby" xreflabel="Reintegrate a failed primary as a standby">
|
||||||
|
<title>How can a failed primary be re-added as a standby?</title>
|
||||||
|
<para>
|
||||||
|
This is a two-stage process. First, the failed primary's data directory
|
||||||
|
must be re-synced with the current primary; secondly the failed primary
|
||||||
|
needs to be re-registered as a standby.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
It's possible to use <command>pg_rewind</command> to re-synchronise the existing data
|
||||||
|
directory, which will usually be much
|
||||||
|
faster than re-cloning the server. However <command>pg_rewind</command> can only
|
||||||
|
be used if PostgreSQL either has <varname>wal_log_hints</varname> enabled, or
|
||||||
|
data checksums were enabled when the cluster was initialized.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Note that <command>pg_rewind</command> is available as part of the core PostgreSQL
|
||||||
|
distribution from PostgreSQL 9.5, and as a third-party utility for PostgreSQL 9.3 and 9.4.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
&repmgr; provides the command <command>repmgr node rejoin</command> which can
|
||||||
|
optionally execute <command>pg_rewind</command>; see the <xref linkend="repmgr-node-rejoin">
|
||||||
|
documentation for details, in particular the section <xref linkend="repmgr-node-rejoin-pg-rewind">.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
If <command>pg_rewind</command> cannot be used, then the data directory will need
|
||||||
|
to be re-cloned from scratch.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
<sect2 id="faq-repmgr-check-configuration" xreflabel="Check PostgreSQL configuration">
|
||||||
|
<title>Is there an easy way to check my primary server is correctly configured for use with &repmgr;?</title>
|
||||||
|
<para>
|
||||||
|
Execute <command><link linkend="repmgr-standby-clone">repmgr standby clone</link></command>
|
||||||
|
with the <literal>--dry-run</literal> option; this will report any configuration problems
|
||||||
|
which need to be rectified.
|
||||||
|
</para>
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
<sect2 id="faq-repmgr-clone-skip-config-files" xreflabel="">
|
||||||
|
<title>When cloning a standby, how can I get &repmgr; to copy
|
||||||
|
<filename>postgresql.conf</filename> and <filename>pg_hba.conf</filename> from the PostgreSQL configuration
|
||||||
|
directory in <filename>/etc</filename>?</title>
|
||||||
|
<para>
|
||||||
|
Use the command line option <literal>--copy-external-config-files</literal>. For more details
|
||||||
|
see <xref linkend="repmgr-standby-clone-config-file-copying">.
|
||||||
|
</para>
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
<sect2 id="faq-repmgr-shared-preload-libaries-no-repmgrd" xreflabel="shared_preload_libraries without repmgrd">
|
||||||
|
<title>Do I need to include <literal>shared_preload_libraries = 'repmgr'</literal>
|
||||||
|
in <filename>postgresql.conf</filename> if I'm not using <application>repmgrd</application>?</title>
|
||||||
|
<para>
|
||||||
|
No, the <literal>repmgr</literal> shared library is only needed when running <application>repmgrd</application>.
|
||||||
|
If you later decide to run <application>repmgrd</application>, you just need to add
|
||||||
|
<literal>shared_preload_libraries = 'repmgr'</literal> and restart PostgreSQL.
|
||||||
|
</para>
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
<sect2 id="faq-repmgr-permissions" xreflabel="Replication permission problems">
|
||||||
|
<title>I've provided replication permission for the <literal>repmgr</literal> user in <filename>pg_hba.conf</filename>
|
||||||
|
but <command>repmgr</command>/<application>repmgrd</application> complains it can't connect to the server... Why?</title>
|
||||||
|
<para>
|
||||||
|
<command>repmgr</command> and <application>repmgrd</application> need to be able to connect to the repmgr database
|
||||||
|
with a normal connection to query metadata. The <literal>replication</literal> connection
|
||||||
|
permission is for PostgreSQL's streaming replication (and doesn't necessarily need to be the <literal>repmgr</literal> user).
|
||||||
|
</para>
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
<sect2 id="faq-repmgr-clone-provide-primary-conninfo" xreflabel="Providing primary connection parameters">
|
||||||
|
<title>When cloning a standby, why do I need to provide the connection parameters
|
||||||
|
for the primary server on the command line, not in the configuration file?</title>
|
||||||
|
<para>
|
||||||
|
Cloning a standby is a one-time action; the role of the server being cloned
|
||||||
|
from could change, so fixing it in the configuration file would create
|
||||||
|
confusion. If &repmgr; needs to establish a connection to the primary
|
||||||
|
server, it can retrieve this from the <literal>repmgr.nodes</literal> table on the local
|
||||||
|
node, and if necessary scan the replication cluster until it locates the active primary.
|
||||||
|
</para>
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
<sect2 id="faq-repmgr-clone-waldir-xlogdir" xreflabel="Providing a custom WAL directory">
|
||||||
|
<title>When cloning a standby, how do I ensure the WAL files are placed in a custom directory?</title>
|
||||||
|
<para>
|
||||||
|
Provide the option <literal>--waldir</literal> (<literal>--xlogdir</literal> in PostgreSQL 9.6
|
||||||
|
and earlier) with the absolute path to the WAL directory in <varname>pg_basebackup_options</varname>.
|
||||||
|
For more details see <xref linkend="cloning-advanced-pg-basebackup-options">.
|
||||||
|
</para>
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
<sect2 id="faq-repmgr-events-no-fkey" xreflabel="No foreign key on node_id in repmgr.events">
|
||||||
|
<title>Why is there no foreign key on the <literal>node_id</literal> column in the <literal>repmgr.events</literal>
|
||||||
|
table?</title>
|
||||||
|
<para>
|
||||||
|
Under some circumstances event notifications can be generated for servers
|
||||||
|
which have not yet been registered; it's also useful to retain a record
|
||||||
|
of events which includes servers removed from the replication cluster
|
||||||
|
which no longer have an entry in the <literal>repmgr.nodes</literal> table.
|
||||||
|
</para>
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
<sect2 id="faq-repmgr-recovery-conf-quoted-values" xreflabel="Quoted values in recovery.conf">
|
||||||
|
<title>Why are some values in <filename>recovery.conf</filename> surrounded by pairs of single quotes?</title>
|
||||||
|
<para>
|
||||||
|
This is to ensure that user-supplied values which are written as parameter values in <filename>recovery.conf</filename>
|
||||||
|
are escaped correctly and do not cause errors when <filename>recovery.conf</filename> is parsed.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The escaping is performed by an internal PostgreSQL routine, which leaves strings consisting
|
||||||
|
of digits and alphabetical characters only as-is, but wraps everything else in pairs of single quotes,
|
||||||
|
even if the string does not contain any characters which need escaping.
|
||||||
|
</para>
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
|
||||||
|
</sect1>
|
||||||
|
|
||||||
|
<sect1 id="faq-repmgrd" xreflabel="repmgrd">
|
||||||
|
<title><application>repmgrd</application></title>
|
||||||
|
|
||||||
|
|
||||||
|
<sect2 id="faq-repmgrd-prevent-promotion" xreflabel="Prevent standby from being promoted to primary">
|
||||||
|
<title>How can I prevent a node from ever being promoted to primary?</title>
|
||||||
|
<para>
|
||||||
|
In <filename>repmgr.conf</filename>, set its priority to a value of <literal>0</literal>; apply the changed setting with
|
||||||
|
<command><link linkend="repmgr-standby-register">repmgr standby register --force</link></command>.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Additionally, if <varname>failover</varname> is set to <literal>manual</literal>, the node will never
|
||||||
|
be considered as a promotion candidate.
|
||||||
|
</para>
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
<sect2 id="faq-repmgrd-delayed-standby" xreflabel="Delayed standby support">
|
||||||
|
<title>Does <application>repmgrd</application> support delayed standbys?</title>
|
||||||
|
<para>
|
||||||
|
<application>repmgrd</application> can monitor delayed standbys - those set up with
|
||||||
|
<varname>recovery_min_apply_delay</varname> set to a non-zero value
|
||||||
|
in <filename>recovery.conf</filename> - but as it's not currently possible
|
||||||
|
to directly examine the value applied to the standby, <application>repmgrd</application>
|
||||||
|
may not be able to properly evaluate the node as a promotion candidate.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
We recommend that delayed standbys are explicitly excluded from promotion
|
||||||
|
by setting <varname>priority</varname> to <literal>0</literal> in
|
||||||
|
<filename>repmgr.conf</filename>.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Note that after registering a delayed standby, <application>repmgrd</application> will only start
|
||||||
|
once the metadata added in the primary node has been replicated.
|
||||||
|
</para>
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
<sect2 id="faq-repmgrd-logfile-rotate" xreflabel="repmgrd logfile rotation">
|
||||||
|
<title>How can I get <application>repmgrd</application> to rotate its logfile?</title>
|
||||||
|
<para>
|
||||||
|
Configure your system's <literal>logrotate</literal> service to do this; see <xref linkend="repmgrd-log-rotation">.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
<sect2 id="faq-repmgrd-recloned-no-start" xreflabel="repmgrd not restarting after node cloned">
|
||||||
|
<title>I've recloned a failed primary as a standby, but <application>repmgrd</application> refuses to start?</title>
|
||||||
|
<para>
|
||||||
|
Check you registered the standby after recloning. If unregistered, the standby
|
||||||
|
cannot be considered as a promotion candidate even if <varname>failover</varname> is set to
|
||||||
|
<literal>automatic</literal>, which is probably not what you want. <application>repmgrd</application> will start if
|
||||||
|
<varname>failover</varname> is set to <literal>manual</literal> so the node's replication status can still
|
||||||
|
be monitored, if desired.
|
||||||
|
</para>
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
<sect2 id="faq-repmgrd-pg-bindir" xreflabel="repmgrd does not apply pg_bindir to promote_command or follow_command">
|
||||||
|
<title>
|
||||||
|
<application>repmgrd</application> ignores pg_bindir when executing <varname>promote_command</varname> or <varname>follow_command</varname>
|
||||||
|
</title>
|
||||||
|
<para>
|
||||||
|
<varname>promote_command</varname> or <varname>follow_command</varname> can be user-defined scripts,
|
||||||
|
so &repmgr; will not apply <option>pg_bindir</option> even if excuting &repmgr;. Always provide the full
|
||||||
|
path; see <xref linkend="repmgrd-automatic-failover-configuration"> for more details.
|
||||||
|
</para>
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
<sect2 id="faq-repmgrd-startup-no-upstream" xreflabel="repmgrd does not start if upstream node is not running">
|
||||||
|
<title>
|
||||||
|
<application>repmgrd</application> aborts startup with the error "<literal>upstream node must be running before repmgrd can start</literal>"
|
||||||
|
</title>
|
||||||
|
<para>
|
||||||
|
<application>repmgrd</application> does this to avoid starting up on a replication cluster
|
||||||
|
which is not in a healthy state. If the upstream is unavailable, <application>repmgrd</application>
|
||||||
|
may initiate a failover immediately after starting up, which could have unintended side-effects,
|
||||||
|
particularly if <application>repmgrd</application> is not running on other nodes.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
In particular, it's possible that the node's local copy of the <literal>repmgr.nodes</literal> copy
|
||||||
|
is out-of-date, which may lead to incorrect failover behaviour.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The onus is therefore on the adminstrator to manually set the cluster to a stable, healthy state before
|
||||||
|
starting <application>repmgrd</application>.
|
||||||
|
</para>
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
</sect1>
|
||||||
|
</appendix>
|
||||||
573
doc/appendix-packages.sgml
Normal file
573
doc/appendix-packages.sgml
Normal file
@@ -0,0 +1,573 @@
|
|||||||
|
<appendix id="appendix-packages" xreflabel="Package details">
|
||||||
|
<indexterm>
|
||||||
|
<primary>packages</primary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<title>&repmgr; package details</title>
|
||||||
|
<para>
|
||||||
|
This section provides technical details about various &repmgr; binary
|
||||||
|
packages, such as location of the installed binaries and
|
||||||
|
configuration files.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<sect1 id="packages-centos" xreflabel="CentOS packages">
|
||||||
|
<title>CentOS Packages</title>
|
||||||
|
|
||||||
|
<indexterm>
|
||||||
|
<primary>packages</primary>
|
||||||
|
<secondary>CentOS packages</secondary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<indexterm>
|
||||||
|
<primary>CentOS</primary>
|
||||||
|
<secondary>package information</secondary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Currently, &repmgr; RPM packages are provided for versions 6.x and 7.x of CentOS. These should also
|
||||||
|
work on matching versions of Red Hat Enterprise Linux, Scientific Linux and Oracle Enterprise Linux;
|
||||||
|
together with CentOS, these are the same RedHat-based distributions for which the main community project
|
||||||
|
(PGDG) provides packages (see the <ulink url="https://yum.postgresql.org/">PostgreSQL RPM Building Project</ulink>
|
||||||
|
page for details).
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Note these &repmgr; RPM packages are not designed to work with SuSE/OpenSuSE.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<note>
|
||||||
|
<para>
|
||||||
|
&repmgr; packages are designed to be compatible with community-provided PostgreSQL packages.
|
||||||
|
They may not work with vendor-specific packages such as those provided by RedHat for RHEL
|
||||||
|
customers, as the filesystem layout may be different to the community RPMs.
|
||||||
|
Please contact your support vendor for assistance.
|
||||||
|
</para>
|
||||||
|
</note>
|
||||||
|
|
||||||
|
<sect2 id="packages-centos-repositories">
|
||||||
|
<title>CentOS repositories</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
&repmgr; packages are available from the public 2ndQuadrant repository, and also the
|
||||||
|
PostgreSQL community repository. The 2ndQuadrant repository is updated immediately
|
||||||
|
after each
|
||||||
|
&repmgr; release.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<table id="centos-2ndquadrant-repository">
|
||||||
|
<title>2ndQuadrant public repository</title>
|
||||||
|
<tgroup cols="2">
|
||||||
|
<tbody>
|
||||||
|
<row>
|
||||||
|
<entry>Repository URL:</entry>
|
||||||
|
<entry><ulink url="https://dl.2ndquadrant.com/">https://dl.2ndquadrant.com/</ulink></entry>
|
||||||
|
</row>
|
||||||
|
<row>
|
||||||
|
<entry>Repository documentation:</entry>
|
||||||
|
<entry><ulink url="https://repmgr.org/docs/current/installation-packages.html#INSTALLATION-PACKAGES-REDHAT-2NDQ">https://repmgr.org/docs/current/installation-packages.html#INSTALLATION-PACKAGES-REDHAT-2NDQ</ulink></entry>
|
||||||
|
</row>
|
||||||
|
</tbody>
|
||||||
|
</tgroup>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<table id="centos-pgdg-repository">
|
||||||
|
<title>PostgreSQL community repository (PGDG)</title>
|
||||||
|
<tgroup cols="2">
|
||||||
|
<tbody>
|
||||||
|
<row>
|
||||||
|
<entry>Repository URL:</entry>
|
||||||
|
<entry><ulink url="https://yum.postgresql.org/repopackages.php">https://yum.postgresql.org/repopackages.php</ulink></entry>
|
||||||
|
</row>
|
||||||
|
<row>
|
||||||
|
<entry>Repository documentation:</entry>
|
||||||
|
<entry><ulink url="https://yum.postgresql.org/">https://yum.postgresql.org/</ulink></entry>
|
||||||
|
</row>
|
||||||
|
</tbody>
|
||||||
|
</tgroup>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
<sect2 id="packages-centos-details">
|
||||||
|
<title>CentOS package details</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
The two tables below list relevant information, paths, commands etc. for the &repmgr; packages on
|
||||||
|
CentOS 7 (with systemd) and CentOS 6 (no systemd). Substitute the appropriate PostgreSQL major
|
||||||
|
version number for your installation.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<note>
|
||||||
|
<para>
|
||||||
|
For PostgreSQL 9.6 and lower, the CentOS packages use a mixture of <literal>9.6</literal>
|
||||||
|
and <literal>96</literal> in various places to designate the major version; e.g. the
|
||||||
|
package name is <literal>repmgr96</literal>, but the binary directory is
|
||||||
|
<filename>/var/lib/pgsql/9.6/data</filename>.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
From PostgreSQL 10, the first part of the version number (e.g. <literal>10</literal>) is
|
||||||
|
the major version, so there is more consistency in file/path/package naming
|
||||||
|
(package <literal>repmgr10</literal>, binary directory <filename>/var/lib/pgsql/10/data</filename>).
|
||||||
|
</para>
|
||||||
|
</note>
|
||||||
|
|
||||||
|
|
||||||
|
<table id="centos-7-packages">
|
||||||
|
<title>CentOS 7 packages</title>
|
||||||
|
|
||||||
|
<tgroup cols="2">
|
||||||
|
<tbody>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry>Package name example:</entry>
|
||||||
|
<entry><filename>repmgr10-4.0.4-1.rhel7.x86_64</filename></entry>
|
||||||
|
</row>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry>Metapackage:</entry>
|
||||||
|
<entry>(none)</entry>
|
||||||
|
</row>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry>Installation command:</entry>
|
||||||
|
<entry><literal>yum install repmgr10</literal></entry>
|
||||||
|
</row>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry>Binary location:</entry>
|
||||||
|
<entry><filename>/usr/pgsql-10/bin</filename></entry>
|
||||||
|
</row>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry>repmgr in default path:</entry>
|
||||||
|
<entry>NO</entry>
|
||||||
|
</row>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry>Configuration file location:</entry>
|
||||||
|
<entry><filename>/etc/repmgr/10/repmgr.conf</filename></entry>
|
||||||
|
</row>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry>Data directory:</entry>
|
||||||
|
<entry><filename>/var/lib/pgsql/10/data</filename></entry>
|
||||||
|
</row>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry>repmgrd service command:</entry>
|
||||||
|
<entry><command>systemctl [start|stop|restart|reload] repmgr10</command></entry>
|
||||||
|
</row>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry>repmgrd service file location:</entry>
|
||||||
|
<entry><filename>/usr/lib/systemd/system/repmgr10.service</filename></entry>
|
||||||
|
</row>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry>repmgrd log file location:</entry>
|
||||||
|
<entry>(not specified by package; set in <filename>repmgr.conf</filename>)</entry>
|
||||||
|
</row>
|
||||||
|
|
||||||
|
</tbody>
|
||||||
|
</tgroup>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<table id="centos-6-packages">
|
||||||
|
<title>CentOS 6 packages</title>
|
||||||
|
|
||||||
|
<tgroup cols="2">
|
||||||
|
<tbody>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry>Package name example:</entry>
|
||||||
|
<entry><filename>repmgr96-4.0.4-1.rhel6.x86_64</filename></entry>
|
||||||
|
</row>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry>Metapackage:</entry>
|
||||||
|
<entry>(none)</entry>
|
||||||
|
</row>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry>Installation command:</entry>
|
||||||
|
<entry><literal>yum install repmgr96</literal></entry>
|
||||||
|
</row>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry>Binary location:</entry>
|
||||||
|
<entry><filename>/usr/pgsql-9.6/bin</filename></entry>
|
||||||
|
</row>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry>repmgr in default path:</entry>
|
||||||
|
<entry>NO</entry>
|
||||||
|
</row>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry>Configuration file location:</entry>
|
||||||
|
<entry><filename>/etc/repmgr/9.6/repmgr.conf</filename></entry>
|
||||||
|
</row>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry>Data directory:</entry>
|
||||||
|
<entry><filename>/var/lib/pgsql/9.6/data</filename></entry>
|
||||||
|
</row>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry>repmgrd service command:</entry>
|
||||||
|
<entry><literal>service [start|stop|restart|reload] repmgr-9.6</literal></entry>
|
||||||
|
</row>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry>repmgrd service file location:</entry>
|
||||||
|
<entry><literal>/etc/init.d/repmgr-9.6</literal></entry>
|
||||||
|
</row>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry>repmgrd log file location:</entry>
|
||||||
|
<entry><filename>/var/log/repmgr/repmgrd-9.6.log</filename></entry>
|
||||||
|
</row>
|
||||||
|
|
||||||
|
</tbody>
|
||||||
|
</tgroup>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
</sect2>
|
||||||
|
</sect1>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<sect1 id="packages-debian-ubuntu" xreflabel="Debian/Ubuntu packages">
|
||||||
|
<title>Debian/Ubuntu Packages</title>
|
||||||
|
<indexterm>
|
||||||
|
<primary>packages</primary>
|
||||||
|
<secondary>Debian/Ubuntu packages</secondary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<indexterm>
|
||||||
|
<primary>Debian/Ubuntu</primary>
|
||||||
|
<secondary>package information</secondary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
&repmgr; <literal>.deb</literal> packages are provided via the
|
||||||
|
PostgreSQL Community APT repository, and are available for each community-supported
|
||||||
|
PostgreSQL version, currently supported Debian releases, and currently supported
|
||||||
|
Ubuntu LTS releases.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<sect2 id="packages-apt-repository">
|
||||||
|
<title>APT repository</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
&repmgr; packages are available from the PostgreSQL Community APT repository,
|
||||||
|
which is updated immediately after each &repmgr; release.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
|
||||||
|
<table id="apt-2ndquadrant-repository">
|
||||||
|
<title>2ndQuadrant public repository</title>
|
||||||
|
<tgroup cols="2">
|
||||||
|
<tbody>
|
||||||
|
<row>
|
||||||
|
<entry>Repository URL:</entry>
|
||||||
|
<entry><ulink url="https://dl.2ndquadrant.com/">https://dl.2ndquadrant.com/</ulink></entry>
|
||||||
|
</row>
|
||||||
|
<row>
|
||||||
|
<entry>Repository documentation:</entry>
|
||||||
|
<entry><ulink url="https://repmgr.org/docs/current/installation-packages.html#INSTALLATION-PACKAGES-DEBIAN">https://repmgr.org/docs/current/installation-packages.html#INSTALLATION-PACKAGES-DEBIAN</ulink></entry>
|
||||||
|
</row>
|
||||||
|
</tbody>
|
||||||
|
</tgroup>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
|
||||||
|
<table id="apt-repository">
|
||||||
|
<title>PostgreSQL Community APT repository (PGDG)</title>
|
||||||
|
<tgroup cols="2">
|
||||||
|
<tbody>
|
||||||
|
<row>
|
||||||
|
<entry>Repository URL:</entry>
|
||||||
|
<entry><ulink url="http://apt.postgresql.org/">http://apt.postgresql.org/</ulink></entry>
|
||||||
|
</row>
|
||||||
|
<row>
|
||||||
|
<entry>Repository documentation:</entry>
|
||||||
|
<entry><ulink url="https://wiki.postgresql.org/wiki/Apt">https://wiki.postgresql.org/wiki/Apt</ulink></entry>
|
||||||
|
</row>
|
||||||
|
</tbody>
|
||||||
|
</tgroup>
|
||||||
|
</table>
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
<sect2 id="packages-debian-details">
|
||||||
|
<title>Debian/Ubuntu package details</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
The table below lists relevant information, paths, commands etc. for the &repmgr; packages on
|
||||||
|
Debian 9.x ("Stretch"). Substitute the appropriate PostgreSQL major
|
||||||
|
version number for your installation.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
See also <xref linkend="repmgrd-configuration-debian-ubuntu"> for some specifics related
|
||||||
|
to configuring the <application>repmgrd</application> daemon.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<table id="debian-9-packages">
|
||||||
|
<title>Debian 9.x packages</title>
|
||||||
|
|
||||||
|
<tgroup cols="2">
|
||||||
|
<tbody>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry>Package name example:</entry>
|
||||||
|
<entry><filename>postgresql-10-repmgr</filename></entry>
|
||||||
|
</row>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry>Metapackage:</entry>
|
||||||
|
<entry><filename>repmgr-common</filename></entry>
|
||||||
|
</row>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry>Installation command:</entry>
|
||||||
|
<entry><literal>apt-get install postgresql-10-repmgr</literal></entry>
|
||||||
|
</row>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry>Binary location:</entry>
|
||||||
|
<entry><filename>/usr/lib/postgresql/10/bin</filename></entry>
|
||||||
|
</row>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry>repmgr in default path:</entry>
|
||||||
|
<entry>Yes (via wrapper script <filename>/usr/bin/repmgr</filename>)</entry>
|
||||||
|
</row>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry>Configuration file location:</entry>
|
||||||
|
<entry>(not set by package)</entry>
|
||||||
|
</row>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry>Data directory:</entry>
|
||||||
|
<entry><filename>/var/lib/postgresql/10/main</filename></entry>
|
||||||
|
</row>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry>PostgreSQL service command:</entry>
|
||||||
|
<entry><command>systemctl [start|stop|restart|reload] postgresql@10-main</command></entry>
|
||||||
|
|
||||||
|
</row>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry>repmgrd service command:</entry>
|
||||||
|
<entry><command>systemctl [start|stop|restart|reload] repmgrd</command></entry>
|
||||||
|
</row>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry>repmgrd service file location:</entry>
|
||||||
|
<entry><filename>/etc/init.d/repmgrd</filename> (defaults in: <filename>/etc/defaults/repmgrd</filename>)</entry>
|
||||||
|
</row>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry>repmgrd log file location:</entry>
|
||||||
|
<entry>(not specified by package; set in <filename>repmgr.conf</filename>)</entry>
|
||||||
|
</row>
|
||||||
|
|
||||||
|
</tbody>
|
||||||
|
</tgroup>
|
||||||
|
</table>
|
||||||
|
<note>
|
||||||
|
<para>
|
||||||
|
Instead of using the <application>systemd</application> service command directly,
|
||||||
|
it's recommended to execute <command>pg_ctlcluster</command> (as <literal>root</literal>,
|
||||||
|
either directly or via <command>sudo</command>), e.g.:
|
||||||
|
<programlisting>
|
||||||
|
<command>pg_ctlcluster 10 main [start|stop|restart|reload]</command></programlisting>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
For pre-<application>systemd</application> systems, <command>pg_ctlcluster</command>
|
||||||
|
can be executed directly by the <literal>postgres</literal> user.
|
||||||
|
</para>
|
||||||
|
</note>
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
</sect1>
|
||||||
|
|
||||||
|
<sect1 id="packages-snapshot" xreflabel="Snapshot packages">
|
||||||
|
<title>Snapshot packages</title>
|
||||||
|
<indexterm>
|
||||||
|
<primary>snapshot packages</primary>
|
||||||
|
</indexterm>
|
||||||
|
<indexterm>
|
||||||
|
<primary>packages</primary>
|
||||||
|
<secondary>snaphots</secondary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
For testing new features and bug fixes, from time to time 2ndQuadrant provides
|
||||||
|
so-called "snapshot packages" via its public repository. These packages
|
||||||
|
are built from the &repmgr; source at a particular point in time, and are not formal
|
||||||
|
releases.
|
||||||
|
</para>
|
||||||
|
<note>
|
||||||
|
<para>
|
||||||
|
We do not recommend installing these packages in a production environment
|
||||||
|
unless specifically advised.
|
||||||
|
</para>
|
||||||
|
</note>
|
||||||
|
<para>
|
||||||
|
To install a snapshot package, it's necessary to install the 2ndQuadrant public snapshot repository,
|
||||||
|
following the instructions here: <ulink url="https://dl.2ndquadrant.com/default/release/site/">https://dl.2ndquadrant.com/default/release/site/</ulink> but replace <literal>release</literal> with <literal>snapshot</literal>
|
||||||
|
in the appropriate URL.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
For example, to install the snapshot RPM repository for PostgreSQL 9.6, execute (as <literal>root</literal>):
|
||||||
|
<programlisting>
|
||||||
|
curl https://dl.2ndquadrant.com/default/snapshot/get/9.6/rpm | bash</programlisting>
|
||||||
|
|
||||||
|
or as a normal user with root sudo access:
|
||||||
|
<programlisting>
|
||||||
|
curl https://dl.2ndquadrant.com/default/snapshot/get/9.6/rpm | sudo bash</programlisting>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Alternatively you can browse the repository here:
|
||||||
|
<ulink url="https://dl.2ndquadrant.com/default/snapshot/browse/">https://dl.2ndquadrant.com/default/snapshot/browse/</ulink>.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Once the repository is installed, installing or updating &repmgr; will result in the latest snapshot
|
||||||
|
package being installed.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The package name will be formatted like this:
|
||||||
|
<programlisting>
|
||||||
|
repmgr96-4.1.1-0.0git320.g5113ab0.1.el7.x86_64.rpm</programlisting>
|
||||||
|
containg the snapshot build number (here: <literal>320</literal>) and the hash
|
||||||
|
of the <application>git</application> commit it was built from (here: <literal>g5113ab0</literal>).
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Note that the next formal release (in the above example <literal>4.1.1</literal>), once available,
|
||||||
|
will install in place of any snapshot builds.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
</sect1>
|
||||||
|
|
||||||
|
<sect1 id="packages-old-versions" xreflabel="Installing old package versions">
|
||||||
|
<title>Installing old package versions</title>
|
||||||
|
|
||||||
|
<indexterm>
|
||||||
|
<primary>old packages</primary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<indexterm>
|
||||||
|
<primary>packages</primary>
|
||||||
|
<secondary>old versions</secondary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<indexterm>
|
||||||
|
<primary>installation</primary>
|
||||||
|
<secondary>old package versions</secondary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<sect2 id="packages-old-versions-debian" xreflabel="old Debian package versions">
|
||||||
|
<title>Debian/Ubuntu</title>
|
||||||
|
<para>
|
||||||
|
An archive of old packages (<literal>3.3.2</literal> and later) for Debian/Ubuntu-based systems is available here:
|
||||||
|
<ulink url="http://atalia.postgresql.org/morgue/r/repmgr/">http://atalia.postgresql.org/morgue/r/repmgr/</ulink>
|
||||||
|
</para>
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
<sect2 id="packages-old-versions-rhel-centos" xreflabel="old RHEL/CentOS package versions">
|
||||||
|
<title>RHEL/CentOS</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Old versions can be located with e.g.:
|
||||||
|
<programlisting>
|
||||||
|
yum --showduplicates list repmgr96</programlisting>
|
||||||
|
(substitute the appropriate package name; see <xref linkend="packages-centos">) and installed with:
|
||||||
|
<programlisting>
|
||||||
|
yum install {package_name}-{version}</programlisting>
|
||||||
|
where <literal>{package_name}</literal> is the base package name (e.g. <literal>repmgr96</literal>)
|
||||||
|
and <literal>{version}</literal> is the version listed by the
|
||||||
|
<command> yum --showduplicates list ...</command> command, e.g. <literal>4.0.6-1.rhel6</literal>.
|
||||||
|
</para>
|
||||||
|
<para>For example:
|
||||||
|
<programlisting>
|
||||||
|
yum install repmgr96-4.0.6-1.rhel6</programlisting>
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<sect3 id="packages-old-versions-rhel-centos-repmgr3">
|
||||||
|
<title>repmgr 3 packages</title>
|
||||||
|
<para>
|
||||||
|
Old &repmgr; 3 RPM packages (<literal>3.2</literal> and later) can be retrieved from the
|
||||||
|
(deprecated) 2ndQuadrant repository at
|
||||||
|
<ulink url="http://packages.2ndquadrant.com/repmgr/yum/">http://packages.2ndquadrant.com/repmgr/yum/</ulink>
|
||||||
|
by installing the appropriate repository RPM:
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<itemizedlist spacing="compact" mark="bullet">
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
<ulink url="http://packages.2ndquadrant.com/repmgr/yum-repo-rpms/repmgr-fedora-1.0-1.noarch.rpm">http://packages.2ndquadrant.com/repmgr/yum-repo-rpms/repmgr-fedora-1.0-1.noarch.rpm</ulink>
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
<ulink url="http://packages.2ndquadrant.com/repmgr/yum-repo-rpms/repmgr-rhel-1.0-1.noarch.rpm">http://packages.2ndquadrant.com/repmgr/yum-repo-rpms/repmgr-rhel-1.0-1.noarch.rpm</ulink>
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
</itemizedlist>
|
||||||
|
</sect3>
|
||||||
|
|
||||||
|
</sect2>
|
||||||
|
</sect1>
|
||||||
|
|
||||||
|
|
||||||
|
<sect1 id="packages-packager-info" xreflabel="Information for packagers">
|
||||||
|
<title>Information for packagers</title>
|
||||||
|
<indexterm>
|
||||||
|
<primary>packages</primary>
|
||||||
|
<secondary>information for packagers</secondary>
|
||||||
|
</indexterm>
|
||||||
|
<para>
|
||||||
|
We recommend patching the following parameters when
|
||||||
|
building the package as built-in default values for user convenience.
|
||||||
|
These values can nevertheless be overridden by the user, if desired.
|
||||||
|
</para>
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Configuration file location: the default configuration file location
|
||||||
|
can be hard-coded by patching <varname>package_conf_file</varname>
|
||||||
|
in <filename>configfile.c</filename>:
|
||||||
|
<programlisting>
|
||||||
|
/* packagers: if feasible, patch configuration file path into "package_conf_file" */
|
||||||
|
char package_conf_file[MAXPGPATH] = "";</programlisting>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
See also: <xref linkend="configuration-file">
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
PID file location: the default <application>repmgrd</application> PID file
|
||||||
|
location can be hard-coded by patching <varname>package_pid_file</varname>
|
||||||
|
in <filename>repmgrd.c</filename>:
|
||||||
|
<programlisting>
|
||||||
|
/* packagers: if feasible, patch PID file path into "package_pid_file" */
|
||||||
|
char package_pid_file[MAXPGPATH] = "";</programlisting>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
See also: <xref linkend="repmgrd-pid-file">
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
</itemizedlist>
|
||||||
|
</sect1>
|
||||||
|
</appendix>
|
||||||
1886
doc/appendix-release-notes.sgml
Normal file
1886
doc/appendix-release-notes.sgml
Normal file
File diff suppressed because it is too large
Load Diff
37
doc/appendix-signatures.sgml
Normal file
37
doc/appendix-signatures.sgml
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
<appendix id="appendix-signatures" xreflabel="Verifying digital signatures">
|
||||||
|
<title>Verifying digital signatures</title>
|
||||||
|
|
||||||
|
<sect1 id="repmgr-source-key" xreflabel="repmgr source key">
|
||||||
|
<title>repmgr source code signing key</title>
|
||||||
|
<para>
|
||||||
|
The signing key ID used for <application>repmgr</application> source code bundles is:
|
||||||
|
<ulink url="https://repmgr.org/download/SOURCE-GPG-KEY-repmgr">
|
||||||
|
<literal>0x297F1DCC</literal></ulink>.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
To download the <application>repmgr</application> source key to your computer:
|
||||||
|
<programlisting>
|
||||||
|
curl -s https://repmgr.org/download/SOURCE-GPG-KEY-repmgr | gpg --import
|
||||||
|
gpg --fingerprint 0x297F1DCC
|
||||||
|
</programlisting>
|
||||||
|
then verify that the fingerprint is the expected value:
|
||||||
|
<programlisting>
|
||||||
|
085A BE38 6FD9 72CE 6365 340D 8365 683D 297F 1DCC</programlisting>
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
For checking tarballs, first download and import the <application>repmgr</application>
|
||||||
|
source signing key as shown above. Then download both source tarball and the detached
|
||||||
|
key (e.g. <filename>repmgr-4.0beta1.tar.gz</filename> and
|
||||||
|
<filename>repmgr-4.0beta1.tar.gz.asc</filename>) from
|
||||||
|
<ulink url="https://repmgr.org/download/">https://repmgr.org/download/</ulink>
|
||||||
|
and use <application>gpg</application> to verify the key, e.g.:
|
||||||
|
<programlisting>
|
||||||
|
gpg --verify repmgr-4.0beta1.tar.gz.asc</programlisting>
|
||||||
|
</para>
|
||||||
|
|
||||||
|
</sect1>
|
||||||
|
|
||||||
|
|
||||||
|
</appendix>
|
||||||
96
doc/appendix-support.sgml
Normal file
96
doc/appendix-support.sgml
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
<appendix id="appendix-support" xreflabel="repmgr support">
|
||||||
|
<indexterm>
|
||||||
|
<primary>support</primary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<title>&repmgr; support</title>
|
||||||
|
<para>
|
||||||
|
<ulink url="https://2ndquadrant.com/">2ndQuadrant</ulink> provides 24x7
|
||||||
|
production support for &repmgr; and other PostgreSQL
|
||||||
|
products, including configuration assistance, installation
|
||||||
|
verification and training for running a robust replication cluster.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
For further details see: <ulink url="https://2ndquadrant.com/en/support/">https://2ndquadrant.com/en/support/</ulink>
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
A mailing list/forum is provided via Google groups to discuss contributions or issues: <ulink url="https://groups.google.com/group/repmgr">https://groups.google.com/group/repmgr</ulink>.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Please report bugs and other issues to: <ulink url="https://github.com/2ndQuadrant/repmgr">https://github.com/2ndQuadrant/repmgr</ulink>.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<important>
|
||||||
|
<para>
|
||||||
|
Please read the <link linkend="appendix-support-reporting-issues">following section</link> before submitting questions or issue reports.
|
||||||
|
</para>
|
||||||
|
</important>
|
||||||
|
|
||||||
|
<sect1 id="appendix-support-reporting-issues" xreflabel="Reportins Issues">
|
||||||
|
<indexterm>
|
||||||
|
<primary>support</primary>
|
||||||
|
<secondary>reporting issues</secondary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<title>Reporting Issues</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
When asking questions or reporting issues, it is extremely helpful if the following information is included:
|
||||||
|
|
||||||
|
<itemizedlist spacing="compact" mark="bullet">
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
&repmgr; version
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
How was &repmgr installed? From source? From packages? If
|
||||||
|
so from which repository?
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
<filename>repmpgr.conf</filename> files (suitably anonymized if necessary)
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
Contents of the <literal>repmgr.nodes</literal> table (suitably anonymized if necessary)
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
PostgreSQL version
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
</itemizedlist>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
If issues are encountered with a &repmgr; client command, please provide
|
||||||
|
the output of that command executed with the options
|
||||||
|
<option>-LDEBUG --verbose</option>, which will ensure &repmgr; emits
|
||||||
|
the maximum level of logging output.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
If issues are encountered with <application>repmgrd</application>,
|
||||||
|
please provide relevant extracts from the &repmgr; log files
|
||||||
|
and if possible the PostgreSQL log itself. Please ensure these
|
||||||
|
logs do not contain any confidential data.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
In all cases it is <emphasis>extremely</emphasis> useful to receive
|
||||||
|
information on how to reliably reproduce an issue with as much detail as
|
||||||
|
possible.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
</sect1>
|
||||||
|
|
||||||
|
</appendix>
|
||||||
@@ -1,288 +1,8 @@
|
|||||||
BDR failover with repmgrd
|
BDR failover with repmgrd
|
||||||
=========================
|
=========================
|
||||||
|
|
||||||
`repmgr 4` provides support for monitoring BDR nodes and taking action in case
|
This document has been integrated into the main `repmgr` documentation
|
||||||
one of the nodes fails.
|
and is now located here:
|
||||||
|
|
||||||
*NOTE* Due to the nature of BDR, it's only safe to use this solution for
|
> [BDR failover with repmgrd](https://repmgr.org/docs/current/repmgrd-bdr.html)
|
||||||
a two-node scenario. Introducing additional nodes will create an inherent
|
|
||||||
risk of node desynchronisation if a node goes down without being cleanly
|
|
||||||
removed from the cluster.
|
|
||||||
|
|
||||||
In contrast to streaming replication, there's no concept of "promoting" a new
|
|
||||||
primary node with BDR. Instead, "failover" involves monitoring both nodes
|
|
||||||
with `repmgrd` and redirecting queries from the failed node to the remaining
|
|
||||||
active node. This can be done by using the event notification script generated by
|
|
||||||
`repmgrd` to dynamically reconfigure a proxy server/connection pooler such
|
|
||||||
as PgBouncer.
|
|
||||||
|
|
||||||
|
|
||||||
Prerequisites
|
|
||||||
-------------
|
|
||||||
|
|
||||||
`repmgr 4` requires PostgreSQL 9.6 with the BDR 2 extension enabled and
|
|
||||||
configured for a two-node BDR network. `repmgr 4` packages
|
|
||||||
must be installed on each node before attempting to configure repmgr.
|
|
||||||
|
|
||||||
*NOTE* `repmgr 4` will refuse to install if it detects more than two
|
|
||||||
BDR nodes.
|
|
||||||
|
|
||||||
Application database connections *must* be passed through a proxy server/
|
|
||||||
connection pooler such as PgBouncer, and it must be possible to dynamically
|
|
||||||
reconfigure that from `repmgrd`. The example demonstrated in this document
|
|
||||||
will use PgBouncer.
|
|
||||||
|
|
||||||
The proxy server / connection poolers must not be installed on the database
|
|
||||||
servers.
|
|
||||||
|
|
||||||
For this example, it's assumed password-less SSH connections are available
|
|
||||||
from the PostgreSQL servers to the servers where PgBouncer runs, and
|
|
||||||
that the user on those servers has permission to alter the PgBouncer
|
|
||||||
configuration files.
|
|
||||||
|
|
||||||
PostgreSQL connections must be possible between each node, and each node
|
|
||||||
must be able to connect to each PgBouncer instance.
|
|
||||||
|
|
||||||
|
|
||||||
Configuration
|
|
||||||
-------------
|
|
||||||
|
|
||||||
Sample configuration for `repmgr.conf`:
|
|
||||||
|
|
||||||
node_id=1
|
|
||||||
node_name='node1'
|
|
||||||
conninfo='host=node1 dbname=bdrtest user=repmgr connect_timeout=2'
|
|
||||||
replication_type='bdr'
|
|
||||||
|
|
||||||
event_notifications=bdr_failover
|
|
||||||
event_notification_command='/path/to/bdr-pgbouncer.sh %n %e %s "%c" "%a" >> /tmp/bdr-failover.log 2>&1'
|
|
||||||
|
|
||||||
# repmgrd options
|
|
||||||
monitor_interval_secs=5
|
|
||||||
reconnect_attempts=6
|
|
||||||
reconnect_interval=5
|
|
||||||
|
|
||||||
Adjust settings as appropriate; copy and adjust for the second node (particularly
|
|
||||||
the values `node_id`, `node_name` and `conninfo`).
|
|
||||||
|
|
||||||
Note that the values provided for the `conninfo` string must be valid for
|
|
||||||
connections from *both* nodes in the cluster. The database must be the BDR
|
|
||||||
database.
|
|
||||||
|
|
||||||
If defined, `event_notifications` will restrict execution of `event_notification_command`
|
|
||||||
to the specified events.
|
|
||||||
|
|
||||||
`event_notification_command` is the script which does the actual "heavy lifting"
|
|
||||||
of reconfiguring the proxy server/ connection pooler. It is fully user-definable;
|
|
||||||
a sample implementation is documented below.
|
|
||||||
|
|
||||||
|
|
||||||
repmgr user permissions
|
|
||||||
-----------------------
|
|
||||||
|
|
||||||
`repmgr` will create an extension in the BDR database containing objects
|
|
||||||
for administering `repmgr` metadata. The user defined in the `conninfo`
|
|
||||||
setting must be able to access all objects. Additionally, superuser permissions
|
|
||||||
are required to install the `repmgr` extension. The easiest way to do this
|
|
||||||
is create the `repmgr` user as a superuser, however if this is not
|
|
||||||
desirable, the `repmgr` user can be created as a normal user and a
|
|
||||||
superuser specified with `--superuser` when registering a BDR node.
|
|
||||||
|
|
||||||
repmgr setup
|
|
||||||
------------
|
|
||||||
|
|
||||||
Register both nodes:
|
|
||||||
|
|
||||||
$ repmgr -f /etc/repmgr.conf bdr register
|
|
||||||
NOTICE: attempting to install extension "repmgr"
|
|
||||||
NOTICE: "repmgr" extension successfully installed
|
|
||||||
NOTICE: node record created for node 'node1' (ID: 1)
|
|
||||||
NOTICE: BDR node 1 registered (conninfo: host=localhost dbname=bdrtest user=repmgr port=5501)
|
|
||||||
|
|
||||||
$ repmgr -f /etc/repmgr.conf bdr register
|
|
||||||
NOTICE: node record created for node 'node2' (ID: 2)
|
|
||||||
NOTICE: BDR node 2 registered (conninfo: host=localhost dbname=bdrtest user=repmgr port=5502)
|
|
||||||
|
|
||||||
The `repmgr` extension will be automatically created when the first
|
|
||||||
node is registered, and will be propagated to the second node.
|
|
||||||
|
|
||||||
*IMPORTANT* ensure the repmgr package is available on both nodes before
|
|
||||||
attempting to register the first node
|
|
||||||
|
|
||||||
|
|
||||||
At this point the meta data for both nodes has been created; executing
|
|
||||||
`repmgr cluster show` (on either node) should produce output like this:
|
|
||||||
|
|
||||||
$ repmgr -f /etc/repmgr.conf cluster show
|
|
||||||
ID | Name | Role | Status | Upstream | Connection string
|
|
||||||
----+-------+------+-----------+----------+--------------------------------------------------------
|
|
||||||
1 | node1 | bdr | * running | | host=node1 dbname=bdrtest user=repmgr connect_timeout=2
|
|
||||||
2 | node2 | bdr | * running | | host=node2 dbname=bdrtest user=repmgr connect_timeout=2
|
|
||||||
|
|
||||||
Additionally it's possible to see a log of significant events; so far
|
|
||||||
this will only record the two node registrations (in reverse chronological order):
|
|
||||||
|
|
||||||
Node ID | Event | OK | Timestamp | Details
|
|
||||||
---------+--------------+----+---------------------+----------------------------------------------
|
|
||||||
2 | bdr_register | t | 2017-07-27 17:51:48 | node record created for node 'node2' (ID: 2)
|
|
||||||
1 | bdr_register | t | 2017-07-27 17:51:00 | node record created for node 'node1' (ID: 1)
|
|
||||||
|
|
||||||
|
|
||||||
Defining the "event_notification_command"
|
|
||||||
-----------------------------------------
|
|
||||||
|
|
||||||
Key to "failover" execution is the `event_notification_command`, which is a
|
|
||||||
user-definable script which should reconfigure the proxy server/
|
|
||||||
connection pooler.
|
|
||||||
|
|
||||||
Each time `repmgr` (or `repmgrd`) records an event, it can optionally
|
|
||||||
execute the script defined in `event_notification_command` to
|
|
||||||
take further action; details of the event will be passed as parameters.
|
|
||||||
Following placeholders are available to the script:
|
|
||||||
|
|
||||||
%n - node ID
|
|
||||||
%e - event type
|
|
||||||
%s - success (1 or 0)
|
|
||||||
%t - timestamp
|
|
||||||
%d - details
|
|
||||||
%c - conninfo string of the next available node
|
|
||||||
%a - name of the next available node
|
|
||||||
|
|
||||||
Note that `%c` and `%a` will only be provided during `bdr_failover`
|
|
||||||
events, which is what is of interest here.
|
|
||||||
|
|
||||||
The provided sample script (`scripts/bdr-pgbouncer.sh`) is configured like
|
|
||||||
this:
|
|
||||||
|
|
||||||
event_notification_command='/path/to/bdr-pgbouncer.sh %n %e %s "%c" "%a"'
|
|
||||||
|
|
||||||
and parses the configures parameters like this:
|
|
||||||
|
|
||||||
NODE_ID=$1
|
|
||||||
EVENT_TYPE=$2
|
|
||||||
SUCCESS=$3
|
|
||||||
NEXT_CONNINFO=$4
|
|
||||||
NEXT_NODE_NAME=$5
|
|
||||||
|
|
||||||
It also contains some hard-coded values about the PgBouncer configuration for
|
|
||||||
both nodes; these will need to be adjusted for your local environment of course
|
|
||||||
(ideally the scripts would be maintained as templates and generated by some
|
|
||||||
kind of provisioning system).
|
|
||||||
|
|
||||||
The script performs following steps:
|
|
||||||
|
|
||||||
- pauses PgBouncer on all nodes
|
|
||||||
- recreates the PgBouncer configuration file on each node using the information
|
|
||||||
provided by `repmgrd` (mainly the `conninfo` string) to configure PgBouncer
|
|
||||||
to point to the remaining node
|
|
||||||
- reloads the PgBouncer configuration
|
|
||||||
- resumes PgBouncer
|
|
||||||
|
|
||||||
From that point, any connections to PgBouncer on the failed BDR node will be redirected
|
|
||||||
to the active node.
|
|
||||||
|
|
||||||
|
|
||||||
repmgrd
|
|
||||||
-------
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Node monitoring and failover
|
|
||||||
----------------------------
|
|
||||||
|
|
||||||
At the intervals specified by `monitor_interval_secs` in `repmgr.conf`, `repmgrd`
|
|
||||||
will ping each node to check if it's available. If a node isn't available,
|
|
||||||
`repmgrd` will enter failover mode and check `reconnect_attempts` times
|
|
||||||
at intervals of `reconnect_interval` to confirm the node is definitely unreachable.
|
|
||||||
This buffer period is necessary to avoid false positives caused by transient
|
|
||||||
network outages.
|
|
||||||
|
|
||||||
If the node is still unavailable, `repmgrd` will enter failover mode and execute
|
|
||||||
the script defined in `event_notification_command`; an entry will be logged
|
|
||||||
in the `repmgr.events` table and `repmgrd` will (unless otherwise configured)
|
|
||||||
resume monitoring of the node in "degraded" mode until it reappears.
|
|
||||||
|
|
||||||
`repmgrd` logfile output during a failover event will look something like this
|
|
||||||
one one node (usually the node which has failed, here "node2"):
|
|
||||||
|
|
||||||
...
|
|
||||||
[2017-07-27 21:08:39] [INFO] starting continuous BDR node monitoring
|
|
||||||
[2017-07-27 21:08:39] [INFO] monitoring BDR replication status on node "node2" (ID: 2)
|
|
||||||
[2017-07-27 21:08:55] [INFO] monitoring BDR replication status on node "node2" (ID: 2)
|
|
||||||
[2017-07-27 21:09:11] [INFO] monitoring BDR replication status on node "node2" (ID: 2)
|
|
||||||
[2017-07-27 21:09:23] [WARNING] unable to connect to node node2 (ID 2)
|
|
||||||
[2017-07-27 21:09:23] [INFO] checking state of node 2, 0 of 5 attempts
|
|
||||||
[2017-07-27 21:09:23] [INFO] sleeping 1 seconds until next reconnection attempt
|
|
||||||
[2017-07-27 21:09:24] [INFO] checking state of node 2, 1 of 5 attempts
|
|
||||||
[2017-07-27 21:09:24] [INFO] sleeping 1 seconds until next reconnection attempt
|
|
||||||
[2017-07-27 21:09:25] [INFO] checking state of node 2, 2 of 5 attempts
|
|
||||||
[2017-07-27 21:09:25] [INFO] sleeping 1 seconds until next reconnection attempt
|
|
||||||
[2017-07-27 21:09:26] [INFO] checking state of node 2, 3 of 5 attempts
|
|
||||||
[2017-07-27 21:09:26] [INFO] sleeping 1 seconds until next reconnection attempt
|
|
||||||
[2017-07-27 21:09:27] [INFO] checking state of node 2, 4 of 5 attempts
|
|
||||||
[2017-07-27 21:09:27] [INFO] sleeping 1 seconds until next reconnection attempt
|
|
||||||
[2017-07-27 21:09:28] [WARNING] unable to reconnect to node 2 after 5 attempts
|
|
||||||
[2017-07-27 21:09:28] [NOTICE] setting node record for node 2 to inactive
|
|
||||||
[2017-07-27 21:09:28] [INFO] executing notification command for event "bdr_failover"
|
|
||||||
[2017-07-27 21:09:28] [DETAIL] command is:
|
|
||||||
/path/to/bdr-pgbouncer.sh 2 bdr_failover 1 "host=host=node1 dbname=bdrtest user=repmgr connect_timeout=2" "node1"
|
|
||||||
[2017-07-27 21:09:28] [INFO] node 'node2' (ID: 2) detected as failed; next available node is 'node1' (ID: 1)
|
|
||||||
[2017-07-27 21:09:28] [INFO] monitoring BDR replication status on node "node2" (ID: 2)
|
|
||||||
[2017-07-27 21:09:28] [DETAIL] monitoring node "node2" (ID: 2) in degraded mode
|
|
||||||
...
|
|
||||||
|
|
||||||
Output on the other node ("node1") during the same event will look like this:
|
|
||||||
|
|
||||||
[2017-07-27 21:08:35] [INFO] starting continuous BDR node monitoring
|
|
||||||
[2017-07-27 21:08:35] [INFO] monitoring BDR replication status on node "node1" (ID: 1)
|
|
||||||
[2017-07-27 21:08:51] [INFO] monitoring BDR replication status on node "node1" (ID: 1)
|
|
||||||
[2017-07-27 21:09:07] [INFO] monitoring BDR replication status on node "node1" (ID: 1)
|
|
||||||
[2017-07-27 21:09:23] [WARNING] unable to connect to node node2 (ID 2)
|
|
||||||
[2017-07-27 21:09:23] [INFO] checking state of node 2, 0 of 5 attempts
|
|
||||||
[2017-07-27 21:09:23] [INFO] sleeping 1 seconds until next reconnection attempt
|
|
||||||
[2017-07-27 21:09:24] [INFO] checking state of node 2, 1 of 5 attempts
|
|
||||||
[2017-07-27 21:09:24] [INFO] sleeping 1 seconds until next reconnection attempt
|
|
||||||
[2017-07-27 21:09:25] [INFO] checking state of node 2, 2 of 5 attempts
|
|
||||||
[2017-07-27 21:09:25] [INFO] sleeping 1 seconds until next reconnection attempt
|
|
||||||
[2017-07-27 21:09:26] [INFO] checking state of node 2, 3 of 5 attempts
|
|
||||||
[2017-07-27 21:09:26] [INFO] sleeping 1 seconds until next reconnection attempt
|
|
||||||
[2017-07-27 21:09:27] [INFO] checking state of node 2, 4 of 5 attempts
|
|
||||||
[2017-07-27 21:09:27] [INFO] sleeping 1 seconds until next reconnection attempt
|
|
||||||
[2017-07-27 21:09:28] [WARNING] unable to reconnect to node 2 after 5 attempts
|
|
||||||
[2017-07-27 21:09:28] [NOTICE] other node's repmgrd is handling failover
|
|
||||||
[2017-07-27 21:09:28] [INFO] monitoring BDR replication status on node "node1" (ID: 1)
|
|
||||||
[2017-07-27 21:09:28] [DETAIL] monitoring node "node2" (ID: 2) in degraded mode
|
|
||||||
|
|
||||||
This assumes only the PostgreSQL instance on "node2" has failed. In this case the
|
|
||||||
`repmgrd` instance running on "node2" has performed the failover. However if
|
|
||||||
the entire server becomes unavailable, `repmgrd` on "node1" will perform
|
|
||||||
the failover.
|
|
||||||
|
|
||||||
|
|
||||||
Node recovery
|
|
||||||
-------------
|
|
||||||
|
|
||||||
Following failure of a BDR node, if the node subsequently becomes available again,
|
|
||||||
a `bdr_recovery` event will be generated. This could potentially be used to
|
|
||||||
reconfigure PgBouncer automatically to bring the node back into the available pool,
|
|
||||||
however it would be prudent to manually verify the node's status before
|
|
||||||
exposing it to the application.
|
|
||||||
|
|
||||||
If the failed node comes back up and connects correctly, output similar to this
|
|
||||||
will be visible in the `repmgrd` log:
|
|
||||||
|
|
||||||
[2017-07-27 21:25:30] [DETAIL] monitoring node "node2" (ID: 2) in degraded mode
|
|
||||||
[2017-07-27 21:25:46] [INFO] monitoring BDR replication status on node "node2" (ID: 2)
|
|
||||||
[2017-07-27 21:25:46] [DETAIL] monitoring node "node2" (ID: 2) in degraded mode
|
|
||||||
[2017-07-27 21:25:55] [INFO] active replication slot for node "node1" found after 1 seconds
|
|
||||||
[2017-07-27 21:25:55] [NOTICE] node "node2" (ID: 2) has recovered after 986 seconds
|
|
||||||
|
|
||||||
|
|
||||||
Shutdown of both nodes
|
|
||||||
----------------------
|
|
||||||
|
|
||||||
If both PostgreSQL instances are shut down, `repmgrd` will try and handle the
|
|
||||||
situation as gracefully as possible, though with no failover candidates available
|
|
||||||
there's not much it can do. Should this case ever occur, we recommend shutting
|
|
||||||
down `repmgrd` on both nodes and restarting it once the PostgreSQL instances
|
|
||||||
are running properly.
|
|
||||||
|
|||||||
@@ -1,106 +1,7 @@
|
|||||||
|
Changes in repmgr 4
|
||||||
|
===================
|
||||||
|
|
||||||
Standardisation on `primary`
|
This document has been integrated into the main `repmgr` documentation
|
||||||
----------------------------
|
and is now located here:
|
||||||
|
|
||||||
To standardise terminology, `primary` is used to denote the read/write
|
> [Release notes](https://repmgr.org/docs/current/release-4.0.html)
|
||||||
node in a streaming replication cluster. `master` is still accepted
|
|
||||||
as a synonym (e.g. `repmgr master register`).
|
|
||||||
|
|
||||||
|
|
||||||
New command line options
|
|
||||||
------------------------
|
|
||||||
|
|
||||||
- `--dry-run`: repmgr will attempt to perform the action as far as possible
|
|
||||||
without making any changes to the database
|
|
||||||
|
|
||||||
- `--upstream-node-id`: use to specify the upstream node the standby will
|
|
||||||
connect later stream from, when cloning a standby. This replaces the configuration
|
|
||||||
file parameter `upstream_node`, as the upstream node is set when the standby
|
|
||||||
is initially cloned, but can change over the lifetime of an installation (due
|
|
||||||
to failovers, switchovers etc.) so it's pointless/confusing keeping the original
|
|
||||||
value around in the config file.
|
|
||||||
|
|
||||||
Changed command line options
|
|
||||||
----------------------------
|
|
||||||
|
|
||||||
### repmgr
|
|
||||||
|
|
||||||
- `--replication-user` has been deprecated; it has been replaced by the
|
|
||||||
configuration file option `replication_user`. The value (which defaults
|
|
||||||
to the user in the `conninfo` string) will be stored in the repmgr metadata
|
|
||||||
for use by standby clone/follow..
|
|
||||||
|
|
||||||
- `--recovery-min-apply-delay` is now a configuration file parameter
|
|
||||||
`recovery_min_apply_delay, to ensure the setting does not get lost when
|
|
||||||
a standby follows a new upstream.
|
|
||||||
|
|
||||||
### repmgrd
|
|
||||||
|
|
||||||
- `--monitoring-history` is deprecated and has been replaced by the
|
|
||||||
configuration file option `monitoring_history`. This enables the
|
|
||||||
setting to be changed without having to modify system service files.
|
|
||||||
|
|
||||||
Changes to repmgr commands
|
|
||||||
--------------------------
|
|
||||||
|
|
||||||
|
|
||||||
### `repmgr cluster show`
|
|
||||||
|
|
||||||
This now displays the role of each node (e.g. `primary`, `standby`)
|
|
||||||
and its status in separate columns.
|
|
||||||
|
|
||||||
The `--csv` option now emits a third column indicating the recovery
|
|
||||||
status of the node.
|
|
||||||
|
|
||||||
|
|
||||||
Configuration file changes
|
|
||||||
--------------------------
|
|
||||||
|
|
||||||
### Required settings
|
|
||||||
|
|
||||||
The following 4 parameters are mandatory in `repmgr.conf`:
|
|
||||||
|
|
||||||
- `node_id`
|
|
||||||
- `node_name`
|
|
||||||
- `conninfo`
|
|
||||||
- `data_directory`
|
|
||||||
|
|
||||||
|
|
||||||
### Renamed settings
|
|
||||||
|
|
||||||
Some settings have been renamed for clarity and consistency:
|
|
||||||
|
|
||||||
- `node`: now `node_id`
|
|
||||||
- `name`: now `node_name`
|
|
||||||
- `master_reponse_timeout`: now `async_query_timeout` to better indicate its
|
|
||||||
purpose
|
|
||||||
|
|
||||||
- The following configuration file parameters have been renamed for consistency
|
|
||||||
with other parameters (and conform to the pattern used by PostgreSQL itself,
|
|
||||||
which uses the prefix `log_` for logging parameters):
|
|
||||||
- `loglevel` has been renamed to `log_level`
|
|
||||||
- `logfile` has been renamed to `log_file`
|
|
||||||
- `logfacility` has been renamed to `log_facility`
|
|
||||||
|
|
||||||
### Removed settings
|
|
||||||
|
|
||||||
- `cluster`: has been removed
|
|
||||||
- `upstream_node`: see note about `--upstream-node-id` above.
|
|
||||||
- `retry_promote_interval_secs`: this is now redundant due to changes in the
|
|
||||||
failover/promotion mechanism; the new equivalent is `primary_notification_timeout`
|
|
||||||
|
|
||||||
|
|
||||||
### Logging changes
|
|
||||||
|
|
||||||
- default value for `log_level` is `INFO` rather than `NOTICE`.
|
|
||||||
- new parameter `log_status_interval`, which causes `repmgrd` to emit a status log
|
|
||||||
line at the specified interval
|
|
||||||
|
|
||||||
|
|
||||||
repmgrd
|
|
||||||
-------
|
|
||||||
|
|
||||||
The `repmgr` shared library has been renamed from `repmgr_funcs` to `repmgr`,
|
|
||||||
meaning `shared_preload_libraries` needs to be updated to the new name:
|
|
||||||
|
|
||||||
shared_preload_libraries = 'repmgr'
|
|
||||||
|
|||||||
469
doc/cloning-standbys.sgml
Normal file
469
doc/cloning-standbys.sgml
Normal file
@@ -0,0 +1,469 @@
|
|||||||
|
<chapter id="cloning-standbys" xreflabel="cloning standbys">
|
||||||
|
<title>Cloning standbys</title>
|
||||||
|
|
||||||
|
<sect1 id="cloning-from-barman" xreflabel="Cloning from Barman">
|
||||||
|
<indexterm>
|
||||||
|
<primary>cloning</primary>
|
||||||
|
<secondary>from Barman</secondary>
|
||||||
|
</indexterm>
|
||||||
|
<indexterm>
|
||||||
|
<primary>Barman</primary>
|
||||||
|
<secondary>cloning a standby</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">
|
||||||
|
<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 section <xref linkend="cloning-from-barman-restore-command">
|
||||||
|
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">
|
||||||
|
<indexterm>
|
||||||
|
<primary>Barman</primary>
|
||||||
|
<secondary>fetching archived WAL</secondary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<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, removing the requirement to use a replication
|
||||||
|
slot for each individual standby 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/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>
|
||||||
|
As &repmgr; uses <command>pg_basebackup</command> to clone a standby, it's possible to
|
||||||
|
provide additional parameters for <command>pg_basebackup</command> to customise the
|
||||||
|
cloning process.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<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 <command><link linkend="repmgr-standby-clone">repmgr standby clone</link></command>'s
|
||||||
|
<literal>-c/--fast-checkpoint</literal> option.
|
||||||
|
Note that this may impact performance of the server being cloned from (typically the primary)
|
||||||
|
so should be used with care.
|
||||||
|
</para>
|
||||||
|
<tip>
|
||||||
|
<simpara>
|
||||||
|
If <application>Barman</application> is set up for the cluster, it's possible to
|
||||||
|
clone the standby directly from Barman, without any impact on the server the standby
|
||||||
|
is being cloned from. For more details see <xref linkend="cloning-from-barman">.
|
||||||
|
</simpara>
|
||||||
|
</tip>
|
||||||
|
<para>
|
||||||
|
Other options can be passed to <command>pg_basebackup</command> by including them
|
||||||
|
in the <filename>repmgr.conf</filename> setting <varname>pg_basebackup_options</varname>.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Not that by default, &repmgr; executes <command>pg_basebackup</command> with <option>-X/--wal-method</option>
|
||||||
|
(PostgreSQL 9.6 and earlier: <option>-X/--xlog-method</option>) set to <literal>stream</literal>.
|
||||||
|
From PostgreSQL 9.6, if replication slots are in use, it will also create a replication slot before
|
||||||
|
running the base backup, and execute <command>pg_basebackup</command> with the
|
||||||
|
<option>-S/--slot</option> option set to the name of the previously created replication slot.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
These parameters can set by the user in <varname>pg_basebackup_options</varname>, in which case they
|
||||||
|
will override the &repmgr; default values. However normally there's no reason to do this.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
If using a separate directory to store WAL files, provide the option <literal>--waldir</literal>
|
||||||
|
(<literal>--xlogdir</literal> in PostgreSQL 9.6 and earlier) with the absolute path to the
|
||||||
|
WAL directory. Any WALs generated during the cloning process will be copied here, and
|
||||||
|
a symlink will automatically be created from the main data directory.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
See the <ulink url="https://www.postgresql.org/docs/current/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>
|
||||||
|
<indexterm>
|
||||||
|
<primary>cloning</primary>
|
||||||
|
<secondary>using passwords</secondary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<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/libpq-pgpass.html">PostgreSQL password file documentation</ulink>.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<note>
|
||||||
|
<para>
|
||||||
|
If using a <filename>pgpass</filename> file, an entry for the replication user (by default the
|
||||||
|
user who connects to the <literal>repmgr</literal> database) <emphasis>must</emphasis>
|
||||||
|
be provided, with database name set to <literal>replication</literal>, e.g.:
|
||||||
|
<programlisting>
|
||||||
|
node1:5432:replication:repmgr:12345</programlisting>
|
||||||
|
</para>
|
||||||
|
</note>
|
||||||
|
|
||||||
|
<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 <varname>primary_conninfo</varname>
|
||||||
|
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>
|
||||||
|
<para>
|
||||||
|
From PostgreSQL 9.6, <application>libpq</application> supports the <varname>passfile</varname>
|
||||||
|
parameter in connection strings, which can be used to specify a password file other than
|
||||||
|
the default <filename>~/.pgpass</filename>.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
To have &repmgr; write a custom password file in <varname>primary_conninfo</varname>,
|
||||||
|
specify its location in <varname>passfile</varname> in <filename>repmgr.conf</filename>.
|
||||||
|
</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 parameter <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>
|
||||||
107
doc/configuration-file-log-settings.sgml
Normal file
107
doc/configuration-file-log-settings.sgml
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
<sect1 id="configuration-file-log-settings" xreflabel="log settings">
|
||||||
|
<indexterm>
|
||||||
|
<primary>repmgr.conf</primary>
|
||||||
|
<secondary>log settings</secondary>
|
||||||
|
</indexterm>
|
||||||
|
<indexterm>
|
||||||
|
<primary>log settings</primary>
|
||||||
|
<secondary>configuration in repmgr.conf</secondary>
|
||||||
|
</indexterm>
|
||||||
|
<title>Log settings</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
By default, &repmgr; and <application>repmgrd</application> write log output to
|
||||||
|
<literal>STDERR</literal>. An alternative log destination can be specified
|
||||||
|
(either a file or <literal>syslog</literal>).
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<note>
|
||||||
|
<para>
|
||||||
|
The &repmgr; application itself will continue to write log output to <literal>STDERR</literal>
|
||||||
|
even if another log destination is configured, as otherwise any output resulting from a command
|
||||||
|
line operation will "disappear" into the log.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
This behaviour can be overriden with the command line option <option>--log-to-file</option>,
|
||||||
|
which will redirect all logging output to the configured log destination. This is recommended
|
||||||
|
when &repmgr; is executed by another application, particularly <application>repmgrd</application>,
|
||||||
|
to enable log output generated by the &repmgr; application to be stored for later reference.
|
||||||
|
</para>
|
||||||
|
</note>
|
||||||
|
|
||||||
|
<variablelist>
|
||||||
|
|
||||||
|
<varlistentry id="repmgr-conf-log-level" xreflabel="log_level">
|
||||||
|
<term><varname>log_level</varname> (<type>string</type>)
|
||||||
|
<indexterm>
|
||||||
|
<primary><varname>log_level</varname> configuration file parameter</primary>
|
||||||
|
</indexterm>
|
||||||
|
</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
One of <option>DEBUG</option>, <option>INFO</option>, <option>NOTICE</option>,
|
||||||
|
<option>WARNING</option>, <option>ERROR</option>, <option>ALERT</option>, <option>CRIT</option>
|
||||||
|
or <option>EMERG</option>.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Default is <option>INFO</option>.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Note that <option>DEBUG</option> will produce a substantial amount of log output
|
||||||
|
and should not be enabled in normal use.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry id="repmgr-conf-log-facility" xreflabel="log_facility">
|
||||||
|
<term><varname>log_facility</varname> (<type>string</type>)
|
||||||
|
<indexterm>
|
||||||
|
<primary><varname>log_facility</varname> configuration file parameter</primary>
|
||||||
|
</indexterm>
|
||||||
|
</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Logging facility: possible values are <option>STDERR</option> (default), or for
|
||||||
|
syslog integration, one of <option>LOCAL0</option>, <option>LOCAL1</option>, <option>...</option>,
|
||||||
|
<option>LOCAL7</option>, <option>USER</option>.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry id="repmgr-conf-log-file" xreflabel="log_file">
|
||||||
|
<term><varname>log_file</varname> (<type>string</type>)
|
||||||
|
<indexterm>
|
||||||
|
<primary><varname>log_file</varname> configuration file parameter</primary>
|
||||||
|
</indexterm>
|
||||||
|
</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
If <xref linkend="repmgr-conf-log-facility"> is set to <option>STDERR</option>, log output
|
||||||
|
can be redirected to the specified file.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
See <xref linkend="repmgrd-log-rotation"> for information on configuring log rotation.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry id="repmgr-conf-log-status-interval" xreflabel="log_status_interval">
|
||||||
|
<term><varname>log_status_interval</varname> (<type>integer</type>)
|
||||||
|
<indexterm>
|
||||||
|
<primary><varname>log_status_interval</varname> configuration file parameter</primary>
|
||||||
|
</indexterm>
|
||||||
|
</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
This setting causes <application>repmgrd</application> to emit a status log
|
||||||
|
line at the specified interval (in seconds, default <literal>300</literal>)
|
||||||
|
describing <application>repmgrd</application>'s current state, e.g.:
|
||||||
|
</para>
|
||||||
|
<programlisting>
|
||||||
|
[2018-07-12 00:47:32] [INFO] monitoring connection to upstream node "node1" (node ID: 1)</programlisting>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
</variablelist>
|
||||||
|
|
||||||
|
</sect1>
|
||||||
126
doc/configuration-file-required-settings.sgml
Normal file
126
doc/configuration-file-required-settings.sgml
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
<sect1 id="configuration-file-settings" xreflabel="required configuration file settings">
|
||||||
|
<indexterm>
|
||||||
|
<primary>repmgr.conf</primary>
|
||||||
|
<secondary>required settings</secondary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<title>Required 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>
|
||||||
|
<para>
|
||||||
|
The string's maximum length is 63 characters and it should
|
||||||
|
contain only printable ASCII characters.
|
||||||
|
</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/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/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</ulink>.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
For <application>repmgrd</application>-specific settings, see <xref linkend="repmgrd-configuration">.
|
||||||
|
</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>
|
||||||
130
doc/configuration-file-service-commands.sgml
Normal file
130
doc/configuration-file-service-commands.sgml
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
<sect1 id="configuration-file-service-commands" xreflabel="service command settings">
|
||||||
|
<indexterm>
|
||||||
|
<primary>repmgr.conf</primary>
|
||||||
|
<secondary>service command settings</secondary>
|
||||||
|
</indexterm>
|
||||||
|
<indexterm>
|
||||||
|
<primary>service command settings</primary>
|
||||||
|
<secondary>configuration in repmgr.conf</secondary>
|
||||||
|
</indexterm>
|
||||||
|
<title>Service command settings</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
In some circumstances, &repmgr; (and <application>repmgrd</application>) need to
|
||||||
|
be able to stop, start or restart PostgreSQL. &repmgr; commands which need to do this
|
||||||
|
include <link linkend="repmgr-standby-follow"><command>repmgr standby follow</command></link>,
|
||||||
|
<link linkend="repmgr-standby-switchover"><command>repmgr standby switchover</command></link> and
|
||||||
|
<link linkend="repmgr-node-rejoin"><command>repmgr node rejoin</command></link>.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
By default, &repmgr; will use PostgreSQL's <command>pg_ctl</command> utility to control the PostgreSQL
|
||||||
|
server. However this can lead to various problems, particularly when PostgreSQL has been
|
||||||
|
installed from packages, and especially so if <application>systemd</application> is in use.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
|
||||||
|
<note>
|
||||||
|
<para>
|
||||||
|
If using <application>systemd</application>, ensure you have <varname>RemoveIPC</varname> set to <literal>off</literal>.
|
||||||
|
See the <ulink url="https://wiki.postgresql.org/wiki/Systemd">systemd</ulink>
|
||||||
|
entry in the <ulink url="https://wiki.postgresql.org/wiki/Main_Page">PostgreSQL wiki</ulink> for details.
|
||||||
|
</para>
|
||||||
|
</note>
|
||||||
|
|
||||||
|
|
||||||
|
<para>
|
||||||
|
With this in mind, we recommend to <emphasis>always</emphasis> configure &repmgr; to use the
|
||||||
|
available system service commands.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
To do this, specify the appropriate command for each action
|
||||||
|
in <filename>repmgr.conf</filename> using the following configuration
|
||||||
|
parameters:
|
||||||
|
<programlisting>
|
||||||
|
service_start_command
|
||||||
|
service_stop_command
|
||||||
|
service_restart_command
|
||||||
|
service_reload_command</programlisting>
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<note>
|
||||||
|
<para>
|
||||||
|
&repmgr; will not apply <option>pg_bindir</option> when executing any of these commands;
|
||||||
|
these can be user-defined scripts so must always be specified with the full path.
|
||||||
|
</para>
|
||||||
|
</note>
|
||||||
|
|
||||||
|
<note>
|
||||||
|
<para>
|
||||||
|
It's also possible to specify a <varname>service_promote_command</varname>.
|
||||||
|
This is intended for systems which provide a package-level promote command,
|
||||||
|
such as Debian's <application>pg_ctlcluster</application>, to promote the
|
||||||
|
PostgreSQL from standby to primary.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
If your packaging system does not provide such a command, it can be left empty,
|
||||||
|
and &repmgr; will generate the appropriate `pg_ctl ... promote` command.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Do not confuse this with <varname>promote_command</varname>, which is used
|
||||||
|
by <application>repmgrd</application> to execute <xref linkend="repmgr-standby-promote">.
|
||||||
|
</para>
|
||||||
|
</note>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
To confirm which command &repmgr; will execute for each action, use
|
||||||
|
<command><link linkend="repmgr-node-service">repmgr node service --list-actions --action=...</link></command>, e.g.:
|
||||||
|
<programlisting>
|
||||||
|
repmgr -f /etc/repmgr.conf node service --list-actions --action=stop
|
||||||
|
repmgr -f /etc/repmgr.conf node service --list-actions --action=start
|
||||||
|
repmgr -f /etc/repmgr.conf node service --list-actions --action=restart
|
||||||
|
repmgr -f /etc/repmgr.conf node service --list-actions --action=reload</programlisting>
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
These commands will be executed by the system user which &repmgr; runs as (usually <literal>postgres</literal>)
|
||||||
|
and will probably require passwordless sudo access to be able to execute the command.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
For example, using <application>systemd</application> on CentOS 7, the service commands can be
|
||||||
|
set as follows:
|
||||||
|
<programlisting>
|
||||||
|
service_start_command = 'sudo systemctl start postgresql-9.6'
|
||||||
|
service_stop_command = 'sudo systemctl stop postgresql-9.6'
|
||||||
|
service_restart_command = 'sudo systemctl restart postgresql-9.6'
|
||||||
|
service_reload_command = 'sudo systemctl reload postgresql-9.6'</programlisting>
|
||||||
|
and <filename>/etc/sudoers</filename> should be set as follows:
|
||||||
|
<programlisting>
|
||||||
|
Defaults:postgres !requiretty
|
||||||
|
postgres ALL = NOPASSWD: /usr/bin/systemctl stop postgresql-9.6, \
|
||||||
|
/usr/bin/systemctl start postgresql-9.6, \
|
||||||
|
/usr/bin/systemctl restart postgresql-9.6, \
|
||||||
|
/usr/bin/systemctl reload postgresql-9.6</programlisting>
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<important>
|
||||||
|
<indexterm>
|
||||||
|
<primary>pg_ctlcluster</primary>
|
||||||
|
<secondary>service command settings</secondary>
|
||||||
|
</indexterm>
|
||||||
|
<para>
|
||||||
|
Debian/Ubuntu users: instead of calling <command>sudo systemctl</command> directly, use
|
||||||
|
<command>sudo pg_ctlcluster</command>, e.g.:
|
||||||
|
<programlisting>
|
||||||
|
service_start_command = 'sudo pg_ctlcluster 9.6 main start'
|
||||||
|
service_stop_command = 'sudo pg_ctlcluster 9.6 main stop'
|
||||||
|
service_restart_command = 'sudo pg_ctlcluster 9.6 main restart'
|
||||||
|
service_reload_command = 'sudo pg_ctlcluster 9.6 main reload'</programlisting>
|
||||||
|
and set <filename>/etc/sudoers</filename> accordingly.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
While <command>pg_ctlcluster</command> will work when executed as user <literal>postgres</literal>,
|
||||||
|
it's strongly recommended to use <command>sudo pg_ctlcluster</command> on <application>systemd</application>
|
||||||
|
systems, to ensure <application>systemd</application> has a correct picture of
|
||||||
|
the PostgreSQL application state.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
</important>
|
||||||
|
|
||||||
|
</sect1>
|
||||||
120
doc/configuration-file.sgml
Normal file
120
doc/configuration-file.sgml
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
<sect1 id="configuration-file" xreflabel="configuration file">
|
||||||
|
<indexterm>
|
||||||
|
<primary>repmgr.conf</primary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<indexterm>
|
||||||
|
<primary>configuration</primary>
|
||||||
|
<secondary>repmgr.conf</secondary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<title>Configuration file</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 <xref linkend="configuration-file-settings">
|
||||||
|
for more details.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<sect2 id="configuration-file-format" xreflabel="configuration file format">
|
||||||
|
|
||||||
|
<indexterm>
|
||||||
|
<primary>repmgr.conf</primary>
|
||||||
|
<secondary>format</secondary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<title>Configuration file format</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
<filename>repmgr.conf</filename> is a plain text file with one parameter/value
|
||||||
|
combination per line.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Whitespace is insignificant (except within a quoted parameter value) and blank lines are ignored.
|
||||||
|
Hash marks (<literal>#</literal>) designate the remainder of the line as a comment.
|
||||||
|
Parameter values that are not simple identifiers or numbers should be single-quoted.
|
||||||
|
Note that single quote cannot be embedded in a parameter value.
|
||||||
|
</para>
|
||||||
|
<important>
|
||||||
|
<para>
|
||||||
|
&repmgr; will interpret double-quotes as being part of a string value; only use single quotes
|
||||||
|
to quote parameter values.
|
||||||
|
</para>
|
||||||
|
</important>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Example of a valid <filename>repmgr.conf</filename> file:
|
||||||
|
<programlisting>
|
||||||
|
# repmgr.conf
|
||||||
|
|
||||||
|
node_id=1
|
||||||
|
node_name= node1
|
||||||
|
conninfo ='host=node1 dbname=repmgr user=repmgr connect_timeout=2'
|
||||||
|
data_directory = /var/lib/pgsql/11/data</programlisting>
|
||||||
|
|
||||||
|
</para>
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<sect2 id="configuration-file-location" xreflabel="configuration file location">
|
||||||
|
<indexterm>
|
||||||
|
<primary>repmgr.conf</primary>
|
||||||
|
<secondary>location</secondary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<title>Configuration file location</title>
|
||||||
|
|
||||||
|
<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 <literal>-f/--config-file</literal> 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 <literal>-f/--config-file</literal>,
|
||||||
|
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 configuration file.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<note>
|
||||||
|
<para>
|
||||||
|
If providing the configuration file location with <literal>-f/--config-file</literal>,
|
||||||
|
avoid using a relative path, particularly when executing <xref linkend="repmgr-primary-register">
|
||||||
|
and <xref linkend="repmgr-standby-register">, as &repmgr; stores the configuration file location
|
||||||
|
in the repmgr metadata for use when &repmgr; is executed remotely (e.g. during
|
||||||
|
<xref linkend="repmgr-standby-switchover">). &repmgr; will attempt to convert the
|
||||||
|
a relative path into an absolute one, but this may not be the same as the path you
|
||||||
|
would explicitly provide (e.g. <filename>./repmgr.conf</filename> might be converted
|
||||||
|
to <filename>/path/to/./repmgr.conf</filename>, whereas you'd normally write
|
||||||
|
<filename>/path/to/repmgr.conf</filename>).
|
||||||
|
</para>
|
||||||
|
</note>
|
||||||
|
|
||||||
|
</sect2>
|
||||||
|
</sect1>
|
||||||
312
doc/configuration.sgml
Normal file
312
doc/configuration.sgml
Normal file
@@ -0,0 +1,312 @@
|
|||||||
|
<chapter id="configuration" xreflabel="Configuration">
|
||||||
|
<title>repmgr configuration</title>
|
||||||
|
|
||||||
|
<sect1 id="configuration-prerequisites" xreflabel="Prerequisites for configuration">
|
||||||
|
<indexterm>
|
||||||
|
<primary>configuration</primary>
|
||||||
|
<secondary>prerequisites</secondary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<indexterm>
|
||||||
|
<primary>configuration</primary>
|
||||||
|
<secondary>ssh</secondary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<title>Prerequisites for configuration</title>
|
||||||
|
<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>
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
At network level, connections between the PostgreSQL port (default: <literal>5432</literal>)
|
||||||
|
must be possible between all nodes.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Passwordless <command>SSH</command> 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 (as is the case with e.g. <link linkend="packages-debian-ubuntu">Debian packages</link>);
|
||||||
|
in this case <command>rsync</command> must also be installed on all servers.
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara>to perform <link linkend="performing-switchover">switchover operations</link></simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
when executing <command><link linkend="repmgr-cluster-matrix">repmgr cluster matrix</link></command>
|
||||||
|
and <command><link linkend="repmgr-cluster-crosscheck">repmgr cluster crosscheck</link></command>
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<tip>
|
||||||
|
<simpara>
|
||||||
|
Consider setting <varname>ConnectTimeout</varname> to a low value in your SSH configuration.
|
||||||
|
This will make it faster to detect any SSH connection errors.
|
||||||
|
</simpara>
|
||||||
|
</tip>
|
||||||
|
|
||||||
|
<sect2 id="configuration-postgresql" xreflabel="PostgreSQL configuration">
|
||||||
|
<indexterm>
|
||||||
|
<primary>configuration</primary>
|
||||||
|
<secondary>PostgreSQL</secondary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<indexterm>
|
||||||
|
<primary>PostgreSQL configuration</primary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<title>PostgreSQL configuration for &repmgr;</title>
|
||||||
|
<para>
|
||||||
|
The following PostgreSQL configuration parameters may need to be changed in order
|
||||||
|
for &repmgr; (and replication itself) to function correctly.
|
||||||
|
</para>
|
||||||
|
<variablelist>
|
||||||
|
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
|
||||||
|
<indexterm>
|
||||||
|
<primary>hot_standby</primary>
|
||||||
|
<secondary>PostgreSQL configuration</secondary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<term><option>hot_standby</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<option>hot_standby</option> must always be set to <literal>on</literal>, as &repmgr; needs
|
||||||
|
to be able to connect to each server it manages.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Note that <option>hot_standby</option> defaults to <literal>on</literal> from PostgreSQL 10
|
||||||
|
and later; in PostgreSQL 9.6 and earlier, the default was <literal>off</literal>.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
PostgreSQL documentation: <ulink url="https://www.postgresql.org/docs/current/runtime-config-replication.html#GUC-HOT-STANDBY">hot_standby</ulink>.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
|
||||||
|
<indexterm>
|
||||||
|
<primary>wal_level</primary>
|
||||||
|
<secondary>PostgreSQL configuration</secondary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<term><option>wal_level</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<option>wal_level</option> must be one of <option>replica</option> or <option>logical</option>
|
||||||
|
(PostgreSQL 9.5 and earlier: one of <option>hot_standby</option> or <option>logical</option>).
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
PostgreSQL documentation: <ulink url="https://www.postgresql.org/docs/current/runtime-config-wal.html#GUC-WAL-LEVEL">wal_level</ulink>.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
|
||||||
|
<indexterm>
|
||||||
|
<primary>max_wal_senders</primary>
|
||||||
|
<secondary>PostgreSQL configuration</secondary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<term><option>max_wal_senders</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<option>max_wal_senders</option> must be set to a value of <literal>2</literal> or greater.
|
||||||
|
In general you will need one WAL sender for each standby which will attach to the PostgreSQL
|
||||||
|
instance; additionally &repmgr; will require two free WAL senders in order to clone further
|
||||||
|
standbys.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
<option>max_wal_senders</option> should be set to an appropriate value on all PostgreSQL
|
||||||
|
instances in the replication cluster which may potentially become a primary server or
|
||||||
|
(in cascading replication) the upstream server of a standby.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
PostgreSQL documentation: <ulink url="https://www.postgresql.org/docs/current/runtime-config-replication.html#GUC-MAX-WAL-SENDERS">max_wal_senders</ulink>.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
|
||||||
|
<indexterm>
|
||||||
|
<primary>max_replication_slots</primary>
|
||||||
|
<secondary>PostgreSQL configuration</secondary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<term><option>max_replication_slots</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
If you are intending to use replication slots, <option>max_replication_slots</option>
|
||||||
|
must be set to a non-zero value.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
<option>max_replication_slots</option> should be set to an appropriate value on all PostgreSQL
|
||||||
|
instances in the replication cluster which may potentially become a primary server or
|
||||||
|
(in cascading replication) the upstream server of a standby.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
PostgreSQL documentation: <ulink url="https://www.postgresql.org/docs/current/runtime-config-replication.html#GUC-MAX-REPLICATION-SLOTS">max_replication_slots</ulink>.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
|
||||||
|
<indexterm>
|
||||||
|
<primary>wal_log_hints</primary>
|
||||||
|
<secondary>PostgreSQL configuration</secondary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<term><option>wal_log_hints</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>If you are intending to use <application>pg_rewind</application>,
|
||||||
|
and the cluster was not initialised using data checksums, you may want to consider enabling
|
||||||
|
<option>wal_log_hints</option>.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
For more details see <xref linkend="repmgr-node-rejoin-pg-rewind">.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
PostgreSQL documentation: <ulink url="https://www.postgresql.org/docs/current/runtime-config-wal.html#GUC-WAL-LOG-HINTS">wal_log_hints</ulink>.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
|
||||||
|
<indexterm>
|
||||||
|
<primary>archive_mode</primary>
|
||||||
|
<secondary>PostgreSQL configuration</secondary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<term><option>archive_mode</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
We suggest setting <option>archive_mode</option> to <literal>on</literal> (and
|
||||||
|
<option>archive_command</option> to <literal>/bin/true</literal>; see below)
|
||||||
|
even if you are currently not planning to use WAL file archiving.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
This will make it simpler to set up WAL file archiving if it is ever required,
|
||||||
|
as changes to <option>archive_mode</option> require a full PostgreSQL server
|
||||||
|
restart, while <option>archive_command</option> changes can be applied via a normal
|
||||||
|
configuration reload.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
However, &repmgr; itself does not require WAL file archiving.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
PostgreSQL documentation: <ulink url="https://www.postgresql.org/docs/current/runtime-config-wal.html#GUC-ARCHIVE-MODE">archive_mode</ulink>.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
|
||||||
|
<indexterm>
|
||||||
|
<primary>archive_command</primary>
|
||||||
|
<secondary>PostgreSQL configuration</secondary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<term><option>archive_command</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
If you have set <option>archive_mode</option> to <literal>on</literal> but are not currently planning
|
||||||
|
to use WAL file archiving, set <option>archive_command</option> to a command which does nothing but returns
|
||||||
|
<literal>true</literal>, such as <command>/bin/true</command>. See above for details.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
PostgreSQL documentation: <ulink url="https://www.postgresql.org/docs/current/runtime-config-wal.html#GUC-ARCHIVE-COMMAND">archive_command</ulink>.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
|
||||||
|
<indexterm>
|
||||||
|
<primary>wal_keep_segments</primary>
|
||||||
|
<secondary>PostgreSQL configuration</secondary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<term><option>wal_keep_segments</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Normally there is no need to set <option>wal_keep_segments</option> (default: <literal>0</literal>), as it
|
||||||
|
is <emphasis>not</emphasis> a reliable way of ensuring that all required WAL segments are available to standbys.
|
||||||
|
Replication slots and/or an archiving solution such as Barman are recommended to ensure standbys have a reliable
|
||||||
|
source of WAL segments at all times.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The only reason ever to set <option>wal_keep_segments</option> is you have
|
||||||
|
you have configured <option>pg_basebackup_options</option>
|
||||||
|
in <filename>repmgr.conf</filename> to include the setting <literal>--wal-method=fetch</literal>
|
||||||
|
(PostgreSQL 9.6 and earlier: <literal>--xlog-method=fetch</literal>)
|
||||||
|
<emphasis>and</emphasis> you have <emphasis>not</emphasis> set <option>restore_command</option>
|
||||||
|
in <filename>repmgr.conf</filename> to fetch WAL files from a reliable source such as Barman,
|
||||||
|
in which case you'll need to set <option>wal_keep_segments</option>
|
||||||
|
to a sufficiently high number to ensure that all WAL files required by the standby
|
||||||
|
are retained. However we do not recommend managing replication in this way.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
PostgreSQL documentation: <ulink url="https://www.postgresql.org/docs/current/runtime-config-replication.html#GUC-WAL-KEEP-SEGMENTS">wal_keep_segments</ulink>.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
</variablelist>
|
||||||
|
<para>
|
||||||
|
See also the <link linkend="quickstart-postgresql-configuration">PostgreSQL configuration</link> section in the
|
||||||
|
<link linkend="quickstart">Quick-start guide</link>.
|
||||||
|
</para>
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
|
||||||
|
</sect1>
|
||||||
|
|
||||||
|
|
||||||
|
&configuration-file;
|
||||||
|
&configuration-file-required-settings;
|
||||||
|
&configuration-file-log-settings;
|
||||||
|
&configuration-file-service-commands;
|
||||||
|
|
||||||
|
<sect1 id="configuration-permissions" xreflabel="Database user permissions">
|
||||||
|
<indexterm>
|
||||||
|
<primary>configuration</primary>
|
||||||
|
<secondary>database user permissions</secondary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<title>repmgr database user permissions</title>
|
||||||
|
<para>
|
||||||
|
&repmgr; will create an extension database containing objects
|
||||||
|
for administering &repmgr; metadata. The user defined in the <varname>conninfo</varname>
|
||||||
|
setting must be able to access all objects. Additionally, superuser permissions
|
||||||
|
are required to install the &repmgr; extension. The easiest way to do this
|
||||||
|
is create the &repmgr; user as a superuser, however if this is not
|
||||||
|
desirable, the &repmgr; user can be created as a normal user and a
|
||||||
|
superuser specified with <literal>--superuser</literal> when registering a &repmgr; node.
|
||||||
|
</para>
|
||||||
|
</sect1>
|
||||||
|
</chapter>
|
||||||
292
doc/event-notifications.sgml
Normal file
292
doc/event-notifications.sgml
Normal file
@@ -0,0 +1,292 @@
|
|||||||
|
<chapter id="event-notifications" xreflabel="event notifications">
|
||||||
|
|
||||||
|
<indexterm>
|
||||||
|
<primary>event notifications</primary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<title>Event Notifications</title>
|
||||||
|
<para>
|
||||||
|
Each time &repmgr; or <application>repmgrd</application> perform a significant event, a record
|
||||||
|
of that event is written into the <literal>repmgr.events</literal> 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 <literal>event_notification_command</literal> parameter in
|
||||||
|
<filename>repmgr.conf</filename>.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The following format placeholders are provided for all event notifications:
|
||||||
|
</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>%s</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
success (1) or failure (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>
|
||||||
|
may 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>
|
||||||
|
The following parameters are provided for a subset of event notifications:
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<variablelist>
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>%p</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
node ID of the current primary (<xref linkend="repmgr-standby-register"> and <xref linkend="repmgr-standby-follow">)
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
node ID of the demoted primary (<xref linkend="repmgr-standby-switchover"> only)
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>%c</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<literal>conninfo</literal> string of the primary node
|
||||||
|
(<xref linkend="repmgr-standby-register"> and <xref linkend="repmgr-standby-follow">)
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
<literal>conninfo</literal> string of the next available node
|
||||||
|
(<varname>bdr_failover</varname> and <varname>bdr_recovery</varname>)
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>%a</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
name of the current primary node (<xref linkend="repmgr-standby-register"> and <xref linkend="repmgr-standby-follow">)
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
name of the next available node (<varname>bdr_failover</varname> and <varname>bdr_recovery</varname>)
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
</variablelist>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
The values provided for <literal>%c</literal> and <literal>%a</literal>
|
||||||
|
will probably contain spaces, so 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 using the
|
||||||
|
<varname>event_notifications</varname> parameter.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Events generated by the &repmgr; command:
|
||||||
|
|
||||||
|
<itemizedlist spacing="compact" mark="bullet">
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara><literal><link linkend="repmgr-primary-register-events">cluster_created</link></literal></simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara><literal><link linkend="repmgr-primary-register-events">primary_register</link></literal></simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara><literal><link linkend="repmgr-primary-unregister-events">primary_unregister</link></literal></simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara><literal><link linkend="repmgr-standby-clone-events">standby_clone</link></literal></simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara><literal><link linkend="repmgr-standby-register-events">standby_register</link></literal></simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara><literal><link linkend="repmgr-standby-register-events">standby_register_sync</link></literal></simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara><literal><link linkend="repmgr-standby-unregister-events">standby_unregister</link></literal></simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara><literal><link linkend="repmgr-standby-promote-events">standby_promote</link></literal></simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara><literal><link linkend="repmgr-standby-follow-events">standby_follow</link></literal></simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara><literal><link linkend="repmgr-standby-switchover-events">standby_switchover</link></literal></simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara><literal><link linkend="repmgr-witness-register-events">witness_register</link></literal></simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara><literal><link linkend="repmgr-witness-unregister-events">witness_unregister</link></literal></simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara><literal><link linkend="repmgr-node-rejoin-events">node_rejoin</link></literal></simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara><literal><link linkend="repmgr-cluster-cleanup-events">cluster_cleanup</link></literal></simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
</itemizedlist>
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Events generated by <application>repmgrd</application> (streaming replication mode):
|
||||||
|
|
||||||
|
<itemizedlist spacing="compact" mark="bullet">
|
||||||
|
<listitem>
|
||||||
|
<simpara><literal>repmgrd_start</literal></simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara><literal>repmgrd_shutdown</literal></simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara><literal>repmgrd_reload</literal></simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara><literal>repmgrd_failover_promote</literal></simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara><literal>repmgrd_failover_follow</literal></simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara><literal>repmgrd_failover_aborted</literal></simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara><literal>repmgrd_standby_reconnect</literal></simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara><literal>repmgrd_promote_error</literal></simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara><literal>repmgrd_local_disconnect</literal></simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara><literal>repmgrd_local_reconnect</literal></simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara><literal>repmgrd_upstream_disconnect</literal></simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara><literal>repmgrd_upstream_reconnect</literal></simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara><literal>standby_disconnect_manual</literal></simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara><literal>standby_failure</literal></simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara><literal>standby_recovery</literal></simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
</itemizedlist>
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Events generated by <application>repmgrd</application> (BDR mode):
|
||||||
|
<itemizedlist spacing="compact" mark="bullet">
|
||||||
|
<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>
|
||||||
90
doc/filelist.sgml
Normal file
90
doc/filelist.sgml
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
<!-- 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-required-settings SYSTEM "configuration-file-required-settings.sgml">
|
||||||
|
<!ENTITY configuration-file-log-settings SYSTEM "configuration-file-log-settings.sgml">
|
||||||
|
<!ENTITY configuration-file-service-commands SYSTEM "configuration-file-service-commands.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-overview SYSTEM "repmgrd-overview.sgml">
|
||||||
|
<!ENTITY repmgrd-automatic-failover SYSTEM "repmgrd-automatic-failover.sgml">
|
||||||
|
<!ENTITY repmgrd-configuration SYSTEM "repmgrd-configuration.sgml">
|
||||||
|
<!ENTITY repmgrd-operation SYSTEM "repmgrd-operation.sgml">
|
||||||
|
<!ENTITY repmgrd-bdr SYSTEM "repmgrd-bdr.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-witness-register SYSTEM "repmgr-witness-register.sgml">
|
||||||
|
<!ENTITY repmgr-witness-unregister SYSTEM "repmgr-witness-unregister.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-node-service SYSTEM "repmgr-node-service.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 repmgr-daemon-status SYSTEM "repmgr-daemon-status.sgml">
|
||||||
|
<!ENTITY repmgr-daemon-start SYSTEM "repmgr-daemon-start.sgml">
|
||||||
|
<!ENTITY repmgr-daemon-stop SYSTEM "repmgr-daemon-stop.sgml">
|
||||||
|
<!ENTITY repmgr-daemon-pause SYSTEM "repmgr-daemon-pause.sgml">
|
||||||
|
<!ENTITY repmgr-daemon-unpause SYSTEM "repmgr-daemon-unpause.sgml">
|
||||||
|
|
||||||
|
<!ENTITY appendix-release-notes SYSTEM "appendix-release-notes.sgml">
|
||||||
|
<!ENTITY appendix-faq SYSTEM "appendix-faq.sgml">
|
||||||
|
<!ENTITY appendix-signatures SYSTEM "appendix-signatures.sgml">
|
||||||
|
<!ENTITY appendix-packages SYSTEM "appendix-packages.sgml">
|
||||||
|
<!ENTITY appendix-support SYSTEM "appendix-support.sgml">
|
||||||
|
|
||||||
|
<!ENTITY bookindex SYSTEM "bookindex.sgml">
|
||||||
|
|
||||||
48
doc/follow-new-primary.sgml
Normal file
48
doc/follow-new-primary.sgml
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
<chapter id="follow-new-primary">
|
||||||
|
<indexterm>
|
||||||
|
<primary>Following a new primary</primary>
|
||||||
|
<seealso>repmgr standby follow</seealso>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<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 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
|
||||||
|
<command><link linkend="repmgr-cluster-show">repmgr cluster show</link></command>
|
||||||
|
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>
|
||||||
274
doc/install-packages.sgml
Normal file
274
doc/install-packages.sgml
Normal file
@@ -0,0 +1,274 @@
|
|||||||
|
<sect1 id="installation-packages" xreflabel="Installing from packages">
|
||||||
|
<title>Installing &repmgr; from packages</title>
|
||||||
|
|
||||||
|
<indexterm>
|
||||||
|
<primary>installation</primary>
|
||||||
|
<secondary>from packages</secondary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
We recommend installing &repmgr; using the available packages for your
|
||||||
|
system.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<sect2 id="installation-packages-redhat" xreflabel="Installing from packages on RHEL, CentOS and Fedora">
|
||||||
|
|
||||||
|
<indexterm>
|
||||||
|
<primary>installation</primary>
|
||||||
|
<secondary>on Red Hat/CentOS/Fedora etc.</secondary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<title>RedHat/CentOS/Fedora</title>
|
||||||
|
<para>
|
||||||
|
&repmgr; RPM packages for RedHat/CentOS variants and Fedora are available from the
|
||||||
|
<ulink url="https://2ndquadrant.com">2ndQuadrant</ulink>
|
||||||
|
<ulink url="https://dl.2ndquadrant.com/">public repository</ulink>; see following
|
||||||
|
section for details.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
RPM packages for &repmgr; are also available via Yum through
|
||||||
|
the PostgreSQL Global Development Group RPM repository
|
||||||
|
(<ulink url="https://yum.postgresql.org/">http://yum.postgresql.org/</ulink>).
|
||||||
|
Follow the instructions for your distribution (RedHat, CentOS,
|
||||||
|
Fedora, etc.) and architecture as detailed there. Note that it can take some days
|
||||||
|
for new &repmgr; packages to become available via the this repository.
|
||||||
|
</para>
|
||||||
|
<note>
|
||||||
|
<para>
|
||||||
|
&repmgr; RPM packages are designed to be compatible with the community-provided PostgreSQL packages
|
||||||
|
and 2ndQuadrant's <ulink url="https://www.2ndquadrant.com/en/resources/2ndqpostgres/">2ndQPostgres</ulink>.
|
||||||
|
They may not work with vendor-specific packages such as those provided by RedHat for RHEL
|
||||||
|
customers, as the PostgreSQL filesystem layout may be different to the community RPMs.
|
||||||
|
Please contact your support vendor for assistance.
|
||||||
|
</para>
|
||||||
|
</note>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
For more information on the package contents, including details of installation
|
||||||
|
paths and relevant <link linkend="configuration-file-service-commands">service commands</link>,
|
||||||
|
see the appendix section <xref linkend="packages-centos">.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
|
||||||
|
<sect3 id="installation-packages-redhat-2ndq">
|
||||||
|
<title>2ndQuadrant public RPM yum repository</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
<ulink url="https://2ndquadrant.com/">2ndQuadrant</ulink> provides a dedicated <literal>yum</literal>
|
||||||
|
<ulink url="https://dl.2ndquadrant.com/">public repository</ulink> for 2ndQuadrant software,
|
||||||
|
including &repmgr;. We recommend using this for all future &repmgr; releases.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
General instructions for using this repository can be found on its
|
||||||
|
<ulink url="https://dl.2ndquadrant.com/">homepage</ulink>. Specific instructions
|
||||||
|
for installing &repmgr; follow below.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
<emphasis>Installation</emphasis>
|
||||||
|
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Locate the repository RPM for your PostgreSQL version from the list at:
|
||||||
|
<ulink url="https://dl.2ndquadrant.com/">https://dl.2ndquadrant.com/</ulink>
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Install the repository definition for your distribution and PostgreSQL version
|
||||||
|
(this enables the 2ndQuadrant repository as a source of &repmgr; packages).
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
For example, for PostgreSQL 10 on CentOS, execute:
|
||||||
|
<programlisting>
|
||||||
|
curl https://dl.2ndquadrant.com/default/release/get/10/rpm | sudo bash</programlisting>
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
For PostgreSQL 9.6 on CentOS, execute:
|
||||||
|
<programlisting>
|
||||||
|
curl https://dl.2ndquadrant.com/default/release/get/9.6/rpm | sudo bash</programlisting>
|
||||||
|
</para>
|
||||||
|
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Verify that the repository is installed with:
|
||||||
|
<programlisting>
|
||||||
|
sudo yum repolist</programlisting>
|
||||||
|
The output should contain two entries like this:
|
||||||
|
<programlisting>
|
||||||
|
2ndquadrant-dl-default-release-pg10/7/x86_64 2ndQuadrant packages (PG10) for 7 - x86_64 4
|
||||||
|
2ndquadrant-dl-default-release-pg10-debug/7/x86_64 2ndQuadrant packages (PG10) for 7 - x86_64 - Debug 3</programlisting>
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Install the &repmgr version appropriate for your PostgreSQL version (e.g. <literal>repmgr10</literal>):
|
||||||
|
<programlisting>
|
||||||
|
sudo yum install repmgr10</programlisting>
|
||||||
|
</para>
|
||||||
|
<note>
|
||||||
|
<para>
|
||||||
|
For packages for PostgreSQL 9.6 and earlier, the package name does not contain
|
||||||
|
a period between major and minor version numbers, e.g.
|
||||||
|
<literal>repmgr96</literal>.
|
||||||
|
</para>
|
||||||
|
</note>
|
||||||
|
<tip>
|
||||||
|
<para>
|
||||||
|
To determine the names of available packages, execute:
|
||||||
|
<programlisting>
|
||||||
|
yum search repmgr</programlisting>
|
||||||
|
</para>
|
||||||
|
</tip>
|
||||||
|
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
<emphasis>Compatibility with PGDG Repositories</emphasis>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The 2ndQuadrant &repmgr; yum repository packages use the same definitions and file system layout as the
|
||||||
|
main PGDG repository.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Normally <application>yum</application> will prioritize the repository with the most recent &repmgr; version.
|
||||||
|
Once the PGDG repository has been updated, it doesn't matter which repository
|
||||||
|
the packages are installed from.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
To ensure the 2ndQuadrant repository is always prioritised, install <literal>yum-plugin-priorities</literal>
|
||||||
|
and set the repository priorities accordingly.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
<emphasis>Installing a specific package version</emphasis>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
To install a specific package version, execute <command>yum --showduplicates list</command>
|
||||||
|
for the package in question:
|
||||||
|
<programlisting>
|
||||||
|
[root@localhost ~]# yum --showduplicates list repmgr10
|
||||||
|
Loaded plugins: fastestmirror
|
||||||
|
Loading mirror speeds from cached hostfile
|
||||||
|
* base: ftp.iij.ad.jp
|
||||||
|
* extras: ftp.iij.ad.jp
|
||||||
|
* updates: ftp.iij.ad.jp
|
||||||
|
Available Packages
|
||||||
|
repmgr10.x86_64 4.0.3-1.rhel7 pgdg10
|
||||||
|
repmgr10.x86_64 4.0.4-1.rhel7 pgdg10
|
||||||
|
repmgr10.x86_64 4.0.5-1.el7 2ndquadrant-repo-10</programlisting>
|
||||||
|
then append the appropriate version number to the package name with a hyphen, e.g.:
|
||||||
|
<programlisting>
|
||||||
|
[root@localhost ~]# yum install repmgr10-4.0.3-1.rhel7</programlisting>
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
<emphasis>Installing old packages</emphasis>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
See appendix <link linkend="packages-old-versions-rhel-centos">Installing old package versions</link>
|
||||||
|
for details on how to retrieve older package versions.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
</sect3>
|
||||||
|
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
<sect2 id="installation-packages-debian" xreflabel="Installing from packages on Debian or Ubuntu">
|
||||||
|
|
||||||
|
<indexterm>
|
||||||
|
<primary>installation</primary>
|
||||||
|
<secondary>on Debian/Ubuntu etc.</secondary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<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/</ulink>).
|
||||||
|
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</ulink>).
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
For more information on the package contents, including details of installation
|
||||||
|
paths and relevant <link linkend="configuration-file-service-commands">service commands</link>,
|
||||||
|
see the appendix section <xref linkend="packages-debian-ubuntu">.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<sect3 id="installation-packages-debian-ubuntu-2ndq">
|
||||||
|
<title>2ndQuadrant public apt repository for Debian/Ubuntu</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
<ulink url="https://2ndquadrant.com/">2ndQuadrant</ulink> provides a
|
||||||
|
<ulink url="https://dl.2ndquadrant.com/">public apt repository</ulink> for 2ndQuadrant software,
|
||||||
|
including &repmgr;.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
General instructions for using this repository can be found on its
|
||||||
|
<ulink url="https://dl.2ndquadrant.com/">homepage</ulink>. Specific instructions
|
||||||
|
for installing &repmgr; follow below.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
|
||||||
|
<emphasis>Installation</emphasis>
|
||||||
|
|
||||||
|
<itemizedlist>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Install the repository definition for your distribution and PostgreSQL version
|
||||||
|
(this enables the 2ndQuadrant repository as a source of &repmgr; packages) by executing:
|
||||||
|
<programlisting>
|
||||||
|
curl https://dl.2ndquadrant.com/default/release/get/deb | sudo bash</programlisting>
|
||||||
|
</para>
|
||||||
|
<note>
|
||||||
|
<para>
|
||||||
|
This will automatically install the following additional packages, if not already present:
|
||||||
|
<itemizedlist spacing="compact" mark="bullet">
|
||||||
|
<listitem>
|
||||||
|
<simpara><literal>lsb-release</literal></simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara><literal>apt-transport-https</literal></simpara>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
</para>
|
||||||
|
</note>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Install the &repmgr version appropriate for your PostgreSQL version (e.g. <literal>repmgr10</literal>):
|
||||||
|
<programlisting>
|
||||||
|
sudo apt-get install postgresql-10-repmgr</programlisting>
|
||||||
|
</para>
|
||||||
|
<note>
|
||||||
|
<para>
|
||||||
|
For packages for PostgreSQL 9.6 and earlier, the package name includes
|
||||||
|
a period between major and minor version numbers, e.g.
|
||||||
|
<literal>postgresql-9.6-repmgr</literal>.
|
||||||
|
</para>
|
||||||
|
</note>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
</itemizedlist>
|
||||||
|
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
<emphasis>Installing old packages</emphasis>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
See appendix <link linkend="packages-old-versions-debian">Installing old package versions</link>
|
||||||
|
for details on how to retrieve older package versions.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
|
||||||
|
</sect3>
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
</sect1>
|
||||||
179
doc/install-requirements.sgml
Normal file
179
doc/install-requirements.sgml
Normal file
@@ -0,0 +1,179 @@
|
|||||||
|
<sect1 id="install-requirements" xreflabel="installation requirements">
|
||||||
|
|
||||||
|
<indexterm>
|
||||||
|
<primary>installation</primary>
|
||||||
|
<secondary>requirements</secondary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<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>
|
||||||
|
&repmgr; 4.x is compatible with all PostgreSQL versions from 9.3. See
|
||||||
|
section <link linkend="install-compatibility-matrix">&repmgr; compatibility matrix</link>
|
||||||
|
for an overview of version compatibility.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<note>
|
||||||
|
<simpara>
|
||||||
|
If upgrading from &repmgr; 3.x, please see the section <xref linkend="upgrading-from-repmgr-3">.
|
||||||
|
</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>
|
||||||
|
|
||||||
|
<note>
|
||||||
|
<simpara>
|
||||||
|
The same "major" &repmgr; version (e.g. <literal>4.2.x</literal>) <emphasis>must</emphasis>
|
||||||
|
be installed on all node in the replication cluster. We strongly recommend keeping all
|
||||||
|
nodes on the same (preferably latest) "minor" &repmgr; version to minimize the risk
|
||||||
|
of incompatibilities.
|
||||||
|
</simpara>
|
||||||
|
<simpara>
|
||||||
|
If different "major" &repmgr; versions (e.g. 3.3.x and 4.1.x)
|
||||||
|
are installed on different nodes, in the best case &repmgr; (in particular <application>repmgrd</application>)
|
||||||
|
will not run. In the worst case, you will end up with a broken cluster.
|
||||||
|
</simpara>
|
||||||
|
</note>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
A dedicated system user for &repmgr; is <emphasis>not</emphasis> required; as many &repmgr; and
|
||||||
|
<application>repmgrd</application> actions require direct access to the PostgreSQL data directory,
|
||||||
|
these commands should be executed by the <literal>postgres</literal> user.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
See also <link linkend="configuration-prerequisites">Prerequisites for configuration</link>
|
||||||
|
for information on networking requirements.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<tip>
|
||||||
|
<simpara>
|
||||||
|
We recommend using a session multiplexer utility such as <command>screen</command> or
|
||||||
|
<command>tmux</command> 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 <command>ssh</command> session to the server is interrupted or closed.
|
||||||
|
</simpara>
|
||||||
|
</tip>
|
||||||
|
|
||||||
|
<sect2 id="install-compatibility-matrix">
|
||||||
|
|
||||||
|
<indexterm>
|
||||||
|
<primary>repmgr</primary>
|
||||||
|
<secondary>compatibility matrix</secondary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<indexterm>
|
||||||
|
<primary>compatibility matrix</primary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<title>&repmgr; compatibility matrix</title>
|
||||||
|
<para>
|
||||||
|
The following table provides an overview of which &repmgr; version supports
|
||||||
|
which PostgreSQL version.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
|
||||||
|
<table id="repmgr-compatibility-matrix">
|
||||||
|
<title>&repmgr; compatibility matrix</title>
|
||||||
|
|
||||||
|
<tgroup cols="2">
|
||||||
|
<thead>
|
||||||
|
<row>
|
||||||
|
<entry>
|
||||||
|
&repmgr; version
|
||||||
|
</entry>
|
||||||
|
<entry>
|
||||||
|
Latest release
|
||||||
|
</entry>
|
||||||
|
<entry>
|
||||||
|
Supported PostgreSQL versions
|
||||||
|
</entry>
|
||||||
|
</row>
|
||||||
|
</thead>
|
||||||
|
|
||||||
|
<tbody>
|
||||||
|
<row>
|
||||||
|
<entry>
|
||||||
|
&repmgr; 4.x
|
||||||
|
</entry>
|
||||||
|
<entry>
|
||||||
|
<link linkend="release-4.2">4.2</link> (2018-10-24)
|
||||||
|
</entry>
|
||||||
|
<entry>
|
||||||
|
9.3, 9.4, 9.5, 9.6, 10, 11
|
||||||
|
</entry>
|
||||||
|
</row>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry>
|
||||||
|
&repmgr; 3.x
|
||||||
|
</entry>
|
||||||
|
<entry>
|
||||||
|
<ulink url="https://repmgr.org/release-notes-3.3.2.html">3.3.2</ulink> (2017-05-30)
|
||||||
|
</entry>
|
||||||
|
<entry>
|
||||||
|
9.3, 9.4, 9.5, 9.6
|
||||||
|
</entry>
|
||||||
|
</row>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry>
|
||||||
|
&repmgr; 2.x
|
||||||
|
</entry>
|
||||||
|
<entry>
|
||||||
|
<ulink url="https://repmgr.org/release-notes-2.0.3.html">2.0.3</ulink> (2015-04-16)
|
||||||
|
</entry>
|
||||||
|
<entry>
|
||||||
|
9.0, 9.1, 9.2, 9.3, 9.4
|
||||||
|
</entry>
|
||||||
|
</row>
|
||||||
|
</tbody>
|
||||||
|
|
||||||
|
</tgroup>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<important>
|
||||||
|
<para>
|
||||||
|
The &repmgr; 2.x and 3.x series are no longer maintained or supported.
|
||||||
|
We strongly recommend upgrading to the latest &repmgr; version.
|
||||||
|
</para>
|
||||||
|
</important>
|
||||||
|
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Note that some &repmgr; functionality is not available in PostgreSQL 9.3 and PostgreSQL 9.4.
|
||||||
|
</para>
|
||||||
|
<itemizedlist spacing="compact" mark="bullet">
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
PostgreSQL 9.3 does not support replication slots, so corresponding &repmgr; functionality
|
||||||
|
is not available.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
In PostgreSQL 9.3 and PostgreSQL 9.4, <command>pg_rewind</command> is not part of the core
|
||||||
|
distribution. <command>pg_rewind</command> will need to be compiled separately to be able
|
||||||
|
to use any &repmgr; functionality which takes advantage of it.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
|
||||||
|
</sect2>
|
||||||
|
</sect1>
|
||||||
271
doc/install-source.sgml
Normal file
271
doc/install-source.sgml
Normal file
@@ -0,0 +1,271 @@
|
|||||||
|
<sect1 id="installation-source" xreflabel="Installing from source code">
|
||||||
|
<indexterm>
|
||||||
|
<primary>installation</primary>
|
||||||
|
<secondary>from source</secondary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<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, and ensure the source repository is enabled.
|
||||||
|
</para>
|
||||||
|
<tip>
|
||||||
|
<para>
|
||||||
|
If not configured, the source repository can be added by including
|
||||||
|
a <literal>deb-src</literal> line as a copy of the existing <literal>deb</literal>
|
||||||
|
line in the repository file, which is usually
|
||||||
|
<filename>/etc/apt/sources.list.d/pgdg.list</filename>, e.g.:
|
||||||
|
<programlisting>
|
||||||
|
deb http://apt.postgresql.org/pub/repos/apt/ stretch-pgdg main
|
||||||
|
deb-src http://apt.postgresql.org/pub/repos/apt/ stretch-pgdg main</programlisting>
|
||||||
|
</para>
|
||||||
|
</tip>
|
||||||
|
<para>
|
||||||
|
Then install the prerequisites for
|
||||||
|
building PostgreSQL with e.g.:
|
||||||
|
<programlisting>
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get build-dep postgresql-9.6</programlisting>
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<important>
|
||||||
|
<simpara>
|
||||||
|
Select the appropriate PostgreSQL version for your target repmgr version.
|
||||||
|
</simpara>
|
||||||
|
</important>
|
||||||
|
|
||||||
|
<note>
|
||||||
|
<para>
|
||||||
|
If using <command>apt-get build-dep</command> is not possible, the
|
||||||
|
following packages may need to be installed manually:
|
||||||
|
|
||||||
|
<itemizedlist spacing="compact" mark="bullet">
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara><literal>libedit-dev</literal></simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara><literal>libkrb5-dev</literal></simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara><literal>libpam0g-dev</literal></simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara><literal>libreadline-dev</literal></simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara><literal>libselinux1-dev</literal></simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara><literal>libssl-dev</literal></simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara><literal>libxml2-dev</literal></simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara><literal>libxslt1-dev</literal></simpara>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
</para>
|
||||||
|
</note>
|
||||||
|
|
||||||
|
</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>
|
||||||
|
|
||||||
|
<important>
|
||||||
|
<simpara>
|
||||||
|
Select the appropriate PostgreSQL version for your target repmgr version.
|
||||||
|
</simpara>
|
||||||
|
</important>
|
||||||
|
<note>
|
||||||
|
<para>
|
||||||
|
If using <command>yum-builddep</command> is not possible, the
|
||||||
|
following packages may need to be installed manually:
|
||||||
|
|
||||||
|
<itemizedlist spacing="compact" mark="bullet">
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara><literal>libselinux-devel</literal></simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara><literal>libxml2-devel</literal></simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara><literal>libxslt-devel</literal></simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara><literal>openssl-devel</literal></simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara><literal>pam-devel</literal></simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara><literal>readline-devel</literal></simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
</itemizedlist>
|
||||||
|
</para>
|
||||||
|
</note>
|
||||||
|
|
||||||
|
<tip>
|
||||||
|
<para>
|
||||||
|
If building against PostgreSQL 11 or later configured with the <option>--with-llvm</option> option
|
||||||
|
(this is the case with the PGDG-provided packages) you'll also need to install the
|
||||||
|
<literal>llvm-toolset-7-clang</literal> package. This is available via the
|
||||||
|
<ulink url="https://wiki.centos.org/AdditionalResources/Repositories/SCL">Software Collections (SCL) Repository</ulink>.
|
||||||
|
</para>
|
||||||
|
</tip>
|
||||||
|
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
</para>
|
||||||
|
|
||||||
|
</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. <literal>v4.2.0</literal>.
|
||||||
|
</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 <command>pg_config</command> for the target PostgreSQL version is in
|
||||||
|
<varname>$PATH</varname>.
|
||||||
|
</para>
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<sect2 id="installation-build-repmgr-docs">
|
||||||
|
<title>Building &repmgr; documentation</title>
|
||||||
|
<para>
|
||||||
|
The &repmgr; documentation is (like the main PostgreSQL project)
|
||||||
|
written in DocBook format. To build it locally as HTML, you'll need to
|
||||||
|
install the required packages as described in the
|
||||||
|
<ulink url="https://www.postgresql.org/docs/9.6/docguide-toolsets.html">
|
||||||
|
PostgreSQL documentation</ulink> then execute:
|
||||||
|
<programlisting>
|
||||||
|
./configure && make install-doc</programlisting>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The generated HTML files will be placed in the <filename>doc/html</filename>
|
||||||
|
subdirectory of your source tree.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
To build the documentation as a single HTML file, execute:
|
||||||
|
<programlisting>
|
||||||
|
cd doc/ && make repmgr.html</programlisting>
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<note>
|
||||||
|
<simpara>
|
||||||
|
Due to changes in PostgreSQL's documentation build system from PostgreSQL 10,
|
||||||
|
the documentation can currently only be built against PostgreSQL 9.6 or earlier.
|
||||||
|
This limitation will be fixed when time and resources permit.
|
||||||
|
</simpara>
|
||||||
|
</note>
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
|
||||||
|
</sect1>
|
||||||
28
doc/install.sgml
Normal file
28
doc/install.sgml
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
<chapter id="installation" xreflabel="Installation">
|
||||||
|
<indexterm>
|
||||||
|
<primary>installation</primary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<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>
|
||||||
37
doc/legal.sgml
Normal file
37
doc/legal.sgml
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
<!-- doc/legal.sgml -->
|
||||||
|
|
||||||
|
<date>2017</date>
|
||||||
|
|
||||||
|
<copyright>
|
||||||
|
<year>2010-2019</year>
|
||||||
|
<holder>2ndQuadrant, Ltd.</holder>
|
||||||
|
</copyright>
|
||||||
|
|
||||||
|
<legalnotice id="legalnotice">
|
||||||
|
<title>Legal Notice</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
<productname>repmgr</productname> is Copyright © 2010-2019
|
||||||
|
by 2ndQuadrant, Ltd. All rights reserved.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
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.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
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.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see
|
||||||
|
<ulink url="https://www.gnu.org/licenses/">https://www.gnu.org/licenses/</ulink>
|
||||||
|
to obtain one.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
</legalnotice>
|
||||||
241
doc/overview.sgml
Normal file
241
doc/overview.sgml
Normal file
@@ -0,0 +1,241 @@
|
|||||||
|
<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">
|
||||||
|
|
||||||
|
<indexterm>
|
||||||
|
<primary>concepts</primary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<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 single PostgreSQL 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 <application>repmgrd</application> 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>
|
||||||
|
<varlistentry id="witness-server">
|
||||||
|
<term>witness server</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
&repmgr; provides functionality to set up a so-called "witness server" to
|
||||||
|
assist in determining a new primary server in a failover situation with more
|
||||||
|
than one standby. The witness server itself is not part of the replication
|
||||||
|
cluster, although it does contain a copy of the repmgr metadata schema.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The purpose of a witness server is to provide a "casting vote" where servers
|
||||||
|
in the replication cluster are split over more than one location. In the event
|
||||||
|
of a loss of connectivity between locations, the presence or absence of
|
||||||
|
the witness server will decide whether a server at that location is promoted
|
||||||
|
to primary; this is to prevent a "split-brain" situation where an isolated
|
||||||
|
location interprets a network outage as a failure of the (remote) primary and
|
||||||
|
promotes a (local) standby.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
A witness server only needs to be created if <application>repmgrd</application>
|
||||||
|
is in use.
|
||||||
|
</para>
|
||||||
|
</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 created by the &repmgr; extension, which is installed
|
||||||
|
during the first step in initializing a &repmgr;-administered cluster
|
||||||
|
(<command><link linkend="repmgr-primary-register">repmgr primary register</link></command>)
|
||||||
|
and contains the following objects:
|
||||||
|
<variablelist>
|
||||||
|
<varlistentry>
|
||||||
|
<term>Tables</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem>
|
||||||
|
<simpara><literal>repmgr.events</literal>: records events of interest</simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara><literal>repmgr.nodes</literal>: connection and status information for each server in the
|
||||||
|
replication cluster</simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara><literal>repmgr.monitoring_history</literal>: historical standby monitoring information
|
||||||
|
written by <application>repmgrd</application></simpara>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>Views</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem>
|
||||||
|
<simpara>repmgr.show_nodes: based on the table <literal>repmgr.nodes</literal>, additionally showing the
|
||||||
|
name of the server's upstream node</simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara>repmgr.replication_status: when <application>repmgrd</application>'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
|
||||||
|
<literal>--superuser</literal>).
|
||||||
|
</para>
|
||||||
|
</sect1>
|
||||||
|
|
||||||
|
</chapter>
|
||||||
79
doc/promoting-standby.sgml
Normal file
79
doc/promoting-standby.sgml
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
<chapter id="promoting-standby" xreflabel="Promoting a standby">
|
||||||
|
<indexterm>
|
||||||
|
<primary>promoting a standby</primary>
|
||||||
|
<seealso>repmgr standby promote</seealso>
|
||||||
|
</indexterm>
|
||||||
|
<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>
|
||||||
|
|
||||||
511
doc/quickstart.sgml
Normal file
511
doc/quickstart.sgml
Normal file
@@ -0,0 +1,511 @@
|
|||||||
|
<chapter id="quickstart" xreflabel="Quick-start guide">
|
||||||
|
<title>Quick-start guide</title>
|
||||||
|
|
||||||
|
<indexterm>
|
||||||
|
<primary>quickstart</primary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<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 for demonstration purposes and are not suitable for a production
|
||||||
|
install, as issues such as account security considerations, and system administration
|
||||||
|
best practices are omitted.
|
||||||
|
</para>
|
||||||
|
<note>
|
||||||
|
<simpara>
|
||||||
|
To upgrade an existing &repmgr; 3.x installation, see section
|
||||||
|
<xref linkend="upgrading-from-repmgr-3">.
|
||||||
|
</simpara>
|
||||||
|
</note>
|
||||||
|
|
||||||
|
<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><link linkend="repmgr-standby-switchover">switchover</link></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" xreflabel="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 value 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).
|
||||||
|
#
|
||||||
|
# See: https://www.postgresql.org/docs/current/runtime-config-replication.html#GUC-MAX-WAL-SENDERS
|
||||||
|
|
||||||
|
max_wal_senders = 10
|
||||||
|
|
||||||
|
# If using replication slots, set this value to at least one more
|
||||||
|
# than the number of standbys which will connect to this server.
|
||||||
|
# Note that repmgr will only make use of replication slots if
|
||||||
|
# "use_replication_slots" is set to "true" in "repmgr.conf".
|
||||||
|
# (If you are not intending to use replication slots, this value
|
||||||
|
# can be set to "0").
|
||||||
|
#
|
||||||
|
# See: https://www.postgresql.org/docs/current/runtime-config-replication.html#GUC-MAX-REPLICATION-SLOTS
|
||||||
|
|
||||||
|
max_replication_slots = 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/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, in case the primary later becomes a standby)
|
||||||
|
#
|
||||||
|
# See: https://www.postgresql.org/docs/current/runtime-config-replication.html#GUC-HOT-STANDBY
|
||||||
|
|
||||||
|
hot_standby = on
|
||||||
|
|
||||||
|
# Enable WAL file archiving
|
||||||
|
#
|
||||||
|
# See: https://www.postgresql.org/docs/current/runtime-config-wal.html#GUC-ARCHIVE-MODE
|
||||||
|
|
||||||
|
archive_mode = on
|
||||||
|
|
||||||
|
# Set archive command to a dummy command; this can later be changed without
|
||||||
|
# needing to restart the PostgreSQL instance.
|
||||||
|
#
|
||||||
|
# See: https://www.postgresql.org/docs/current/runtime-config-wal.html#GUC-ARCHIVE-COMMAND
|
||||||
|
|
||||||
|
archive_command = '/bin/true'
|
||||||
|
</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>
|
||||||
|
<para>
|
||||||
|
Additionally, if you are intending to use <application>pg_rewind</application>,
|
||||||
|
and the cluster was not initialised using data checksums, you may want to consider enabling
|
||||||
|
<varname>wal_log_hints</varname>; for more details see <xref linkend="repmgr-node-rejoin-pg-rewind">.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
See also the <link linkend="configuration-postgresql">PostgreSQL configuration</link> section in the
|
||||||
|
<link linkend="configuration">repmgr configuration guide</link>.
|
||||||
|
</para>
|
||||||
|
</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 <emphasis>not</emphasis> create a PostgreSQL instance (i.e.
|
||||||
|
do not execute <application>initdb</application> or any database creation
|
||||||
|
scripts provided by packages), 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>
|
||||||
|
<tip>
|
||||||
|
<simpara>
|
||||||
|
&repmgr; will place a copy of the primary's database files in this directory.
|
||||||
|
It will however refuse to run if a PostgreSQL instance has already been
|
||||||
|
created there.
|
||||||
|
</simpara>
|
||||||
|
</tip>
|
||||||
|
<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/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 <xref linkend="configuration"> and <xref linkend="configuration-file">
|
||||||
|
for further details about <filename>repmgr.conf</filename>.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<note>
|
||||||
|
<para>
|
||||||
|
&repmgr; only uses <option>pg_bindir</option> when it executes
|
||||||
|
PostgreSQL binaries directly.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
For user-defined scripts such as <option>promote_command</option> and the
|
||||||
|
various <option>service_*_command</option>s, you <emphasis>must</emphasis>
|
||||||
|
always explicitly provide the full path to the binary or script being
|
||||||
|
executed, even if it is &repmgr; itself.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
This is because these options can contain user-defined scripts in arbitrary
|
||||||
|
locations, so prepending <option>pg_bindir</option> may break them.
|
||||||
|
</para>
|
||||||
|
</note>
|
||||||
|
|
||||||
|
<tip>
|
||||||
|
<simpara>
|
||||||
|
For Debian-based distributions we recommend explictly setting
|
||||||
|
<option>pg_bindir</option> 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>
|
||||||
|
|
||||||
|
<tip>
|
||||||
|
<simpara>
|
||||||
|
If your distribution places the &repmgr; binaries in a location other than the
|
||||||
|
PostgreSQL installation directory, specify this with <option>repmgr_bindir</option>
|
||||||
|
to enable &repmgr; to perform operations (e.g.
|
||||||
|
<command><link linkend="repmgr-cluster-crosscheck">repmgr cluster crosscheck</link></command>)
|
||||||
|
on other nodes.
|
||||||
|
</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 <application>repmgrd</application>
|
||||||
|
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_id=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/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>
|
||||||
77
doc/repmgr-cluster-cleanup.sgml
Normal file
77
doc/repmgr-cluster-cleanup.sgml
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
<refentry id="repmgr-cluster-cleanup">
|
||||||
|
<indexterm>
|
||||||
|
<primary>repmgr cluster cleanup</primary>
|
||||||
|
</indexterm>
|
||||||
|
<refmeta>
|
||||||
|
<refentrytitle>repmgr cluster cleanup</refentrytitle>
|
||||||
|
</refmeta>
|
||||||
|
|
||||||
|
<refnamediv>
|
||||||
|
<refname>repmgr cluster cleanup</refname>
|
||||||
|
<refpurpose>purge monitoring history</refpurpose>
|
||||||
|
</refnamediv>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Description</title>
|
||||||
|
<para>
|
||||||
|
Purges monitoring history from the <literal>repmgr.monitoring_history</literal> table to
|
||||||
|
prevent excessive table growth.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
By default <emphasis>all</emphasis> data will be removed; Use the <option>-k/--keep-history</option>
|
||||||
|
option to specify the number of days of monitoring history to retain.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
This command can be executed manually or as a cronjob.
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Usage</title>
|
||||||
|
<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>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Notes</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Monitoring history will only be written if <application>repmgrd</application> is active, and
|
||||||
|
<varname>monitoring_history</varname> is set to <literal>true</literal> in
|
||||||
|
<filename>repmgr.conf</filename>.
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1 id="repmgr-cluster-cleanup-events">
|
||||||
|
<title>Event notifications</title>
|
||||||
|
<para>
|
||||||
|
A <literal>cluster_cleanup</literal> <link linkend="event-notifications">event notification</link> will be generated.
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Options</title>
|
||||||
|
<variablelist>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--node-id</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Only delete monitoring records for the specified node.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>See also</title>
|
||||||
|
<para>
|
||||||
|
For more details see the sections <xref linkend="repmgrd-monitoring"> and
|
||||||
|
<xref linkend="repmgrd-monitoring-configuration">.
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
</refentry>
|
||||||
96
doc/repmgr-cluster-crosscheck.sgml
Normal file
96
doc/repmgr-cluster-crosscheck.sgml
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
<refentry id="repmgr-cluster-crosscheck">
|
||||||
|
<indexterm>
|
||||||
|
<primary>repmgr cluster crosscheck</primary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
|
||||||
|
<refmeta>
|
||||||
|
<refentrytitle>repmgr cluster crosscheck</refentrytitle>
|
||||||
|
</refmeta>
|
||||||
|
|
||||||
|
<refnamediv>
|
||||||
|
<refname>repmgr cluster crosscheck</refname>
|
||||||
|
<refpurpose>cross-checks connections between each combination of nodes</refpurpose>
|
||||||
|
</refnamediv>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Description</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><link linkend="repmgr-cluster-matrix">repmgr cluster matrix</link></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>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Exit codes</title>
|
||||||
|
<para>
|
||||||
|
One of the following exit codes will be emitted by <command>repmgr cluster crosscheck</command>:
|
||||||
|
</para>
|
||||||
|
<variablelist>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>SUCCESS (0)</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
The check completed successfully and all nodes are reachable.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>ERR_BAD_SSH (12)</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
One or more nodes could not be accessed via SSH.
|
||||||
|
</para>
|
||||||
|
<note>
|
||||||
|
<simpara>
|
||||||
|
This only applies to nodes unreachable from the node where
|
||||||
|
this command is executed.
|
||||||
|
</simpara>
|
||||||
|
<simpara>
|
||||||
|
It's also possible that the crosscheck establishes that
|
||||||
|
connections between PostgreSQL on all nodes are functioning,
|
||||||
|
even if SSH access between some nodes is not possible.
|
||||||
|
</simpara>
|
||||||
|
</note>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>ERR_NODE_STATUS (25)</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
PostgreSQL on one or more nodes could not be reached.
|
||||||
|
</para>
|
||||||
|
<note>
|
||||||
|
<simpara>
|
||||||
|
This error code overrides <option>ERR_BAD_SSH</option>.
|
||||||
|
</simpara>
|
||||||
|
</note>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
</variablelist>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
</refentry>
|
||||||
|
|
||||||
79
doc/repmgr-cluster-event.sgml
Normal file
79
doc/repmgr-cluster-event.sgml
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
<refentry id="repmgr-cluster-event">
|
||||||
|
<indexterm>
|
||||||
|
<primary>repmgr cluster event</primary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<refmeta>
|
||||||
|
<refentrytitle>repmgr cluster event</refentrytitle>
|
||||||
|
</refmeta>
|
||||||
|
|
||||||
|
<refnamediv>
|
||||||
|
<refname>repmgr cluster event</refname>
|
||||||
|
<refpurpose>output a formatted list of cluster events</refpurpose>
|
||||||
|
</refnamediv>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Description</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Outputs a formatted list of cluster events, as stored in the <literal>repmgr.events</literal> table.
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Usage</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
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 (see <xref linkend="event-notifications"> for a full list)</simpara>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The "Details" column can be omitted by providing <literal>--terse</literal>.
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Output format</title>
|
||||||
|
<para>
|
||||||
|
<itemizedlist spacing="compact" mark="bullet">
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
<literal>--csv</literal>: generate output in CSV format. Note that the <literal>Details</literal>
|
||||||
|
column will currently not be emitted in CSV format.
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
</itemizedlist>
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Example</title>
|
||||||
|
<para>
|
||||||
|
<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>
|
||||||
|
</refsect1>
|
||||||
|
</refentry>
|
||||||
145
doc/repmgr-cluster-matrix.sgml
Normal file
145
doc/repmgr-cluster-matrix.sgml
Normal file
@@ -0,0 +1,145 @@
|
|||||||
|
<refentry id="repmgr-cluster-matrix">
|
||||||
|
<indexterm>
|
||||||
|
<primary>repmgr cluster matrix</primary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<refmeta>
|
||||||
|
<refentrytitle>repmgr cluster matrix</refentrytitle>
|
||||||
|
</refmeta>
|
||||||
|
|
||||||
|
<refnamediv>
|
||||||
|
<refname>repmgr cluster matrix</refname>
|
||||||
|
<refpurpose>
|
||||||
|
runs repmgr cluster show on each node and summarizes output
|
||||||
|
</refpurpose>
|
||||||
|
</refnamediv>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Description</title>
|
||||||
|
<para>
|
||||||
|
<command>repmgr cluster matrix</command> runs <command><link linkend="repmgr-cluster-show">repmgr cluster show</link></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 <command>ssh</command> connections are required between
|
||||||
|
all nodes.
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Example</title>
|
||||||
|
<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 <literal>*</literal> 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>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Exit codes</title>
|
||||||
|
<para>
|
||||||
|
One of the following exit codes will be emitted by <command>repmgr cluster matrix</command>:
|
||||||
|
</para>
|
||||||
|
<variablelist>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>SUCCESS (0)</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
The check completed successfully and all nodes are reachable.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>ERR_BAD_SSH (12)</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
One or more nodes could not be accessed via SSH.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>ERR_NODE_STATUS (25)</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
PostgreSQL on one or more nodes could not be reached.
|
||||||
|
</para>
|
||||||
|
<note>
|
||||||
|
<simpara>
|
||||||
|
This error code overrides <option>ERR_BAD_SSH</option>.
|
||||||
|
</simpara>
|
||||||
|
</note>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
</variablelist>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
</refentry>
|
||||||
|
|
||||||
238
doc/repmgr-cluster-show.sgml
Normal file
238
doc/repmgr-cluster-show.sgml
Normal file
@@ -0,0 +1,238 @@
|
|||||||
|
<refentry id="repmgr-cluster-show">
|
||||||
|
<indexterm>
|
||||||
|
<primary>repmgr cluster show</primary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<refmeta>
|
||||||
|
<refentrytitle>repmgr cluster show</refentrytitle>
|
||||||
|
</refmeta>
|
||||||
|
|
||||||
|
<refnamediv>
|
||||||
|
<refname>repmgr cluster show</refname>
|
||||||
|
<refpurpose>display information about each registered node in the replication cluster</refpurpose>
|
||||||
|
</refnamediv>
|
||||||
|
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Description</title>
|
||||||
|
<para>
|
||||||
|
Displays information about each registered 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>
|
||||||
|
Node 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
|
||||||
|
better overviews of connections between nodes.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Execution</title>
|
||||||
|
<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>
|
||||||
|
To show database connection errors when polling nodes, run the command in
|
||||||
|
<literal>--verbose</literal> mode.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Example</title>
|
||||||
|
<para>
|
||||||
|
<programlisting>
|
||||||
|
$ repmgr -f /etc/repmgr.conf cluster show
|
||||||
|
|
||||||
|
ID | Name | Role | Status | Upstream | Location | Priority | Connection string
|
||||||
|
----+-------+---------+-----------+----------+----------+----------+-----------------------------------------
|
||||||
|
1 | node1 | primary | * running | | default | 100 | host=db_node1 dbname=repmgr user=repmgr
|
||||||
|
2 | node2 | standby | running | node1 | default | 100 | host=db_node2 dbname=repmgr user=repmgr
|
||||||
|
3 | node3 | standby | running | node1 | default | 100 | host=db_node3 dbname=repmgr user=repmgr</programlisting>
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
<refsect1>
|
||||||
|
<title>Notes</title>
|
||||||
|
<para>
|
||||||
|
The column <literal>Role</literal> shows the expected server role according to the
|
||||||
|
&repmgr; metadata.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
<literal>Status</literal> shows whether the server is running or unreachable.
|
||||||
|
If the node has an unexpected role not reflected in the &repmgr; metadata, e.g. a node was manually
|
||||||
|
promoted to primary, this will be highlighted with an exclamation mark.
|
||||||
|
If a connection to the node cannot be made, this will be highlighted with a question mark.
|
||||||
|
Note that the node will only be shown as <literal>? unreachable</literal>
|
||||||
|
if a connection is not possible at network level; if the PostgreSQL instance on the
|
||||||
|
node is pingable but not accepting connections, it will be shown as <literal>? running</literal>.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
In the following example, executed on <literal>node3</literal>, <literal>node1</literal> is not reachable
|
||||||
|
at network level and assumed to be down; <literal>node2</literal> has been promoted to primary
|
||||||
|
(but <literal>node3</literal> is not attached to it, and its metadata has not yet been updated);
|
||||||
|
<literal>node4</literal> is running but rejecting connections (from <literal>node3</literal> at least).
|
||||||
|
<programlisting>
|
||||||
|
ID | Name | Role | Status | Upstream | Location | Priority | Connection string
|
||||||
|
----+-------+---------+----------------------+----------+----------+----------+-----------------------------------------
|
||||||
|
1 | node1 | primary | ? unreachable | | default | 100 | host=db_node1 dbname=repmgr user=repmgr
|
||||||
|
2 | node2 | standby | ! running as primary | node1 | default | 100 | host=db_node2 dbname=repmgr user=repmgr
|
||||||
|
3 | node3 | standby | running | node1 | default | 100 | host=db_node3 dbname=repmgr user=repmgr
|
||||||
|
4 | node4 | standby | ? running | node1 | default | 100 | host=db_node4 dbname=repmgr user=repmgr
|
||||||
|
|
||||||
|
WARNING: following issues were detected
|
||||||
|
- unable to connect to node "node1" (ID: 1)
|
||||||
|
- node "node1" (ID: 1) is registered as an active primary but is unreachable
|
||||||
|
- node "node2" (ID: 2) is registered as standby but running as primary
|
||||||
|
- unable to connect to node "node4" (ID: 4)
|
||||||
|
HINT: execute with --verbose option to see connection error messages</programlisting>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
To diagnose connection issues, execute <command>repmgr cluster show</command>
|
||||||
|
with the <option>--verbose</option> option; this will display the error message
|
||||||
|
for each failed connection attempt.
|
||||||
|
</para>
|
||||||
|
<tip>
|
||||||
|
<para>
|
||||||
|
Use <xref linkend="repmgr-cluster-matrix"> and <xref linkend="repmgr-cluster-crosscheck">
|
||||||
|
to diagnose connection issues across the whole replication cluster.
|
||||||
|
</para>
|
||||||
|
</tip>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Options</title>
|
||||||
|
|
||||||
|
<variablelist>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--csv</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<command>repmgr 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, e.g.:
|
||||||
|
<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>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
availability (0 = available, -1 = unavailable)
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
recovery state (0 = not in recovery, 1 = in recovery, -1 = unknown)
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--compact</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Suppress display of the <literal>conninfo</literal> column.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--terse</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Suppress warnings about connection issues.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--verbose</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Display the full text of any database connection error messages
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
</variablelist>
|
||||||
|
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Exit codes</title>
|
||||||
|
<para>
|
||||||
|
One of the following exit codes will be emitted by <command>repmgr cluster show</command>:
|
||||||
|
</para>
|
||||||
|
<variablelist>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>SUCCESS (0)</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
No issues were detected.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>ERR_BAD_CONFIG (1)</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
An issue was encountered while attempting to retrieve
|
||||||
|
&repmgr; metadata.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>ERR_DB_CONN (6)</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
&repmgr; was unable to connect to the local PostgreSQL instance.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>ERR_NODE_STATUS (25)</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
One or more issues were detected with the replication configuration,
|
||||||
|
e.g. a node was not in its expected state.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
</variablelist>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>See also</title>
|
||||||
|
<para>
|
||||||
|
<xref linkend="repmgr-node-status">, <xref linkend="repmgr-node-check">, <xref linkend="repmgr-daemon-status">
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
</refentry>
|
||||||
114
doc/repmgr-daemon-pause.sgml
Normal file
114
doc/repmgr-daemon-pause.sgml
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
<refentry id="repmgr-daemon-pause">
|
||||||
|
<indexterm>
|
||||||
|
<primary>repmgr daemon pause</primary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<indexterm>
|
||||||
|
<primary>repmgrd</primary>
|
||||||
|
<secondary>pausing</secondary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<refmeta>
|
||||||
|
<refentrytitle>repmgr daemon pause</refentrytitle>
|
||||||
|
</refmeta>
|
||||||
|
|
||||||
|
<refnamediv>
|
||||||
|
<refname>repmgr daemon pause</refname>
|
||||||
|
<refpurpose>Instruct all <application>repmgrd</application> instances in the replication cluster to pause failover operations</refpurpose>
|
||||||
|
</refnamediv>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Description</title>
|
||||||
|
<para>
|
||||||
|
This command can be run on any active node in the replication cluster to instruct all
|
||||||
|
running <application>repmgrd</application> instances to "pause" themselves, i.e. take no
|
||||||
|
action (such as promoting themselves or following a new primary) if a failover event is detected.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
This functionality is useful for performing maintenance operations, such as switchovers
|
||||||
|
or upgrades, which might otherwise trigger a failover if <application>repmgrd</application>
|
||||||
|
is running normally.
|
||||||
|
</para>
|
||||||
|
<note>
|
||||||
|
<para>
|
||||||
|
It's important to wait a few seconds after restarting PostgreSQL on any node before running
|
||||||
|
<command>repmgr daemon pause</command>, as the <application>repmgrd</application> instance
|
||||||
|
on the restarted node will take a second or two before it has updated its status.
|
||||||
|
</para>
|
||||||
|
</note>
|
||||||
|
<para>
|
||||||
|
<xref linkend="repmgr-daemon-unpause"> will instruct all previously paused <application>repmgrd</application>
|
||||||
|
instances to resume normal failover operation.
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Execution</title>
|
||||||
|
<para>
|
||||||
|
<command>repmgr daemon pause</command> can be executed on any active node in the
|
||||||
|
replication cluster. A valid <filename>repmgr.conf</filename> file is required.
|
||||||
|
It will have no effect on previously paused nodes.
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Example</title>
|
||||||
|
<para>
|
||||||
|
<programlisting>
|
||||||
|
$ repmgr -f /etc/repmgr.conf daemon pause
|
||||||
|
NOTICE: node 1 (node1) paused
|
||||||
|
NOTICE: node 2 (node2) paused
|
||||||
|
NOTICE: node 3 (node3) paused</programlisting>
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Options</title>
|
||||||
|
<variablelist>
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--dry-run</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Check if nodes are reachable but don't pause <application>repmgrd</application>.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Exit codes</title>
|
||||||
|
<para>
|
||||||
|
One of the following exit codes will be emitted by <command>repmgr daemon unpause</command>:
|
||||||
|
</para>
|
||||||
|
<variablelist>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>SUCCESS (0)</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<application>repmgrd</application> could be paused on all nodes.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>ERR_REPMGRD_PAUSE (26)</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<application>repmgrd</application> could not be paused on one or mode nodes.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
</variablelist>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>See also</title>
|
||||||
|
<para>
|
||||||
|
<xref linkend="repmgr-daemon-unpause">, <xref linkend="repmgr-daemon-status">
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
</refentry>
|
||||||
|
|
||||||
203
doc/repmgr-daemon-start.sgml
Normal file
203
doc/repmgr-daemon-start.sgml
Normal file
@@ -0,0 +1,203 @@
|
|||||||
|
<refentry id="repmgr-daemon-start">
|
||||||
|
<indexterm>
|
||||||
|
<primary>repmgr daemon start</primary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<indexterm>
|
||||||
|
<primary>repmgrd</primary>
|
||||||
|
<secondary>starting</secondary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<refmeta>
|
||||||
|
<refentrytitle>repmgr daemon start</refentrytitle>
|
||||||
|
</refmeta>
|
||||||
|
|
||||||
|
<refnamediv>
|
||||||
|
<refname>repmgr daemon start</refname>
|
||||||
|
<refpurpose>Start the <application>repmgrd</application> daemon</refpurpose>
|
||||||
|
</refnamediv>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Description</title>
|
||||||
|
<para>
|
||||||
|
This command starts the <application>repmgrd</application> daemon on the
|
||||||
|
local node.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
By default, &repmgr; will wait for up to 15 seconds to confirm that <application>repmgrd</application>
|
||||||
|
started. This behaviour can be overridden by specifying a diffent value using the <option>--wait</option>
|
||||||
|
option, or disabled altogether with the <option>--no-wait</option> option.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<important>
|
||||||
|
<para>
|
||||||
|
The <filename>repmgr.conf</filename> parameter <varname>repmgrd_service_start_command</varname>
|
||||||
|
must be set for <command>repmgr daemon start</command> to work; see section
|
||||||
|
<xref linkend="repmgr-daemon-start-configuration"> for details.
|
||||||
|
</para>
|
||||||
|
</important>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
|
||||||
|
<title>Options</title>
|
||||||
|
|
||||||
|
<variablelist>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--dry-run</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Check prerequisites but don't actually attempt to start <application>repmgrd</application>.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
This action will output the command which would be executed.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>-w</option></term>
|
||||||
|
<term><option>--wait</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Wait for the specified number of seconds to confirm that <application>repmgrd</application>
|
||||||
|
started successfully.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Note that providing <option>--wait=0</option> is the equivalent of <option>--no-wait</option>.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--no-wait</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Don't wait to confirm that <application>repmgrd</application>
|
||||||
|
started successfully.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
This is equivalent to providing <option>--wait=0</option>.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
</variablelist>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1 id="repmgr-daemon-start-configuration" xreflabel="repmgr daemon start configuration">
|
||||||
|
<title>Configuration file settings</title>
|
||||||
|
<para>
|
||||||
|
The following parameter in <filename>repmgr.conf</filename> is relevant
|
||||||
|
to <command>repmgr daemon start</command>:
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<variablelist>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<indexterm>
|
||||||
|
<primary>repmgrd_service_start_command</primary>
|
||||||
|
<secondary>with "repmgr daemon start"</secondary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<term><option>repmgrd_service_start_command</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<command>repmgr daemon start</command> will execute the command defined by the
|
||||||
|
<varname>repmgrd_service_start_command</varname> parameter in <filename>repmgr.conf</filename>.
|
||||||
|
This must be set to a shell command which will start <application>repmgrd</application>;
|
||||||
|
if &repmgr; was installed from a package, this will be the service command defined by the
|
||||||
|
package. For more details see <link linkend="appendix-packages">Appendix: &repmgr; package details</link>.
|
||||||
|
</para>
|
||||||
|
<important>
|
||||||
|
<para>
|
||||||
|
If &repmgr; was installed from a system package, and you do not configure
|
||||||
|
<varname>repmgrd_service_start_command</varname> to an appropriate service command, this may
|
||||||
|
result in the system becoming confused about the state of the <application>repmgrd</application>
|
||||||
|
service; this is particularly the case with <literal>systemd</literal>.
|
||||||
|
</para>
|
||||||
|
</important>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Exit codes</title>
|
||||||
|
<para>
|
||||||
|
One of the following exit codes will be emitted by <command>repmgr daemon start</command>:
|
||||||
|
</para>
|
||||||
|
<variablelist>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>SUCCESS (0)</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
The <application>repmgrd</application> start command (defined in
|
||||||
|
<varname>repmgrd_service_start_command</varname>) was successfully executed.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
If the <option>--wait</option> option was provided, &repmgr; will confirm that
|
||||||
|
<application>repmgrd</application> has actually started up.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>ERR_BAD_CONFIG (1)</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<varname>repmgrd_service_start_command</varname> is not defined in
|
||||||
|
<filename>repmgr.conf</filename>.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>ERR_DB_CONN (6)</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
&repmgr; was unable to connect to the local PostgreSQL node.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
PostgreSQL must be running before <application>repmgrd</application>
|
||||||
|
can be started. Additionally, unless the <option>--no-wait</option> option was
|
||||||
|
provided, &repmgr; needs to be able to connect to the local PostgreSQL node
|
||||||
|
to determine the state of <application>repmgrd</application>.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>ERR_REPMGRD_SERVICE (27)</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
The <application>repmgrd</application> start command (defined in
|
||||||
|
<varname>repmgrd_service_start_command</varname>) was not successfully executed.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
This can also mean that &repmgr; was unable to confirm whether <application>repmgrd</application>
|
||||||
|
successfully started (unless the <option>--no-wait</option> option was provided).
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
</variablelist>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>See also</title>
|
||||||
|
<para>
|
||||||
|
<xref linkend="repmgr-daemon-stop">, <xref linkend="repmgr-daemon-status">, <xref linkend="repmgrd-daemon">
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
</refentry>
|
||||||
186
doc/repmgr-daemon-status.sgml
Normal file
186
doc/repmgr-daemon-status.sgml
Normal file
@@ -0,0 +1,186 @@
|
|||||||
|
<refentry id="repmgr-daemon-status">
|
||||||
|
<indexterm>
|
||||||
|
<primary>repmgr daemon status</primary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<indexterm>
|
||||||
|
<primary>repmgrd</primary>
|
||||||
|
<secondary>displaying daemon status</secondary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<refmeta>
|
||||||
|
<refentrytitle>repmgr daemon status</refentrytitle>
|
||||||
|
</refmeta>
|
||||||
|
|
||||||
|
<refnamediv>
|
||||||
|
<refname>repmgr daemon status</refname>
|
||||||
|
<refpurpose>display information about the status of <application>repmgrd</application> on each node in the cluster</refpurpose>
|
||||||
|
</refnamediv>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Description</title>
|
||||||
|
<para>
|
||||||
|
This command provides an overview over all active nodes in the cluster and the state
|
||||||
|
of each node's <application>repmgrd</application> instance. It can be used to check
|
||||||
|
the result of <xref linkend="repmgr-daemon-pause"> and <xref linkend="repmgr-daemon-unpause">
|
||||||
|
operations.
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Execution</title>
|
||||||
|
<para>
|
||||||
|
<command>repmgr daemon status</command> can be executed on any active node in the
|
||||||
|
replication cluster. A valid <filename>repmgr.conf</filename> file is required.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
If PostgreSQL is not running on a node, &repmgr; will not be able to determine the
|
||||||
|
status of that node's <application>repmgrd</application> instance.
|
||||||
|
</para>
|
||||||
|
<note>
|
||||||
|
<para>
|
||||||
|
After restarting PostgreSQL on any node, the <application>repmgrd</application> instance
|
||||||
|
will take a second or two before it is able to update its status. Until then,
|
||||||
|
<application>repmgrd</application> will be shown as not running.
|
||||||
|
</para>
|
||||||
|
</note>
|
||||||
|
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Examples</title>
|
||||||
|
<para>
|
||||||
|
<application>repmgrd</application> running normally on all nodes:
|
||||||
|
<programlisting>$ repmgr -f /etc/repmgr.conf daemon status
|
||||||
|
ID | Name | Role | Priority | Status | repmgrd | PID | Paused? | Upstream last seen
|
||||||
|
----+-------+---------+----------+---------+---------+-------+---------+--------------------
|
||||||
|
1 | node1 | primary | 100 | running | running | 71987 | no | n/a
|
||||||
|
2 | node2 | standby | 100 | running | running | 71996 | no | 1 second(s) ago
|
||||||
|
3 | node3 | standby | 100 | running | running | 72042 | no | 1 second(s) ago
|
||||||
|
</programlisting>
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
<application>repmgrd</application> paused on all nodes (using <xref linkend="repmgr-daemon-pause">):
|
||||||
|
<programlisting>$ repmgr -f /etc/repmgr.conf daemon status
|
||||||
|
ID | Name | Role | Priority | Status | repmgrd | PID | Paused? | Upstream last seen
|
||||||
|
----+-------+---------+----------+---------+---------+-------+---------+--------------------
|
||||||
|
1 | node1 | primary | 100 | running | running | 71987 | yes | n/a
|
||||||
|
2 | node2 | standby | 100 | running | running | 71996 | yes | 0 second(s) ago
|
||||||
|
3 | node3 | standby | 100 | running | running | 72042 | yes | 0 second(s) ago
|
||||||
|
</programlisting>
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
<application>repmgrd</application> not running on one node:
|
||||||
|
<programlisting>$ repmgr -f /etc/repmgr.conf daemon status
|
||||||
|
ID | Name | Role | Priority | Status | repmgrd | PID | Paused? | Upstream last seen
|
||||||
|
----+-------+---------+----------+---------+-------------+-------+---------+--------------------
|
||||||
|
1 | node1 | primary | 100 | running | running | 71987 | yes | n/a
|
||||||
|
2 | node2 | standby | 100 | running | not running | n/a | n/a | n/a
|
||||||
|
3 | node3 | standby | 100 | running | running | 72042 | yes | 0 second(s) ago</programlisting>
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Options</title>
|
||||||
|
|
||||||
|
<variablelist>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--csv</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<command>repmgr daemon status</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, e.g.:
|
||||||
|
<programlisting>
|
||||||
|
$ repmgr -f /etc/repmgr.conf daemon status --csv
|
||||||
|
1,node1,primary,1,1,5722,1,100,-1
|
||||||
|
2,node2,standby,1,0,-1,1,100,1
|
||||||
|
3,node3,standby,1,1,5779,1,100,1</programlisting>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The columns have following meanings:
|
||||||
|
<itemizedlist spacing="compact" mark="bullet">
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
node ID
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
node name
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
node type (primary or standby)
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
PostgreSQL server running (1 = running, 0 = not running)
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
<application>repmgrd</application> running (1 = running, 0 = not running, -1 = unknown)
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
<application>repmgrd</application> PID (-1 if not running or status unknown)
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
<application>repmgrd</application> paused (1 = paused, 0 = not paused, -1 = unknown)
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
<application>repmgrd</application> node priority
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
interval in seconds since the node's upstream was last seen (this will be -1 if the value could not be retrieved, or the node is primary)
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
</itemizedlist>
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--verbose</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Display the full text of any database connection error messages
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
</variablelist>
|
||||||
|
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>See also</title>
|
||||||
|
<para>
|
||||||
|
<xref linkend="repmgr-daemon-pause">, <xref linkend="repmgr-daemon-unpause">, <xref linkend="repmgr-cluster-show">
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
</refentry>
|
||||||
200
doc/repmgr-daemon-stop.sgml
Normal file
200
doc/repmgr-daemon-stop.sgml
Normal file
@@ -0,0 +1,200 @@
|
|||||||
|
<refentry id="repmgr-daemon-stop">
|
||||||
|
<indexterm>
|
||||||
|
<primary>repmgr daemon stop</primary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<indexterm>
|
||||||
|
<primary>repmgrd</primary>
|
||||||
|
<secondary>stopping</secondary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<refmeta>
|
||||||
|
<refentrytitle>repmgr daemon stop</refentrytitle>
|
||||||
|
</refmeta>
|
||||||
|
|
||||||
|
<refnamediv>
|
||||||
|
<refname>repmgr daemon stop</refname>
|
||||||
|
<refpurpose>Stop the <application>repmgrd</application> daemon</refpurpose>
|
||||||
|
</refnamediv>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Description</title>
|
||||||
|
<para>
|
||||||
|
This command stops the <application>repmgrd</application> daemon on the
|
||||||
|
local node.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
By default, &repmgr; will wait for up to 15 seconds to confirm that <application>repmgrd</application>
|
||||||
|
stopped. This behaviour can be overridden by specifying a diffent value using the <option>--wait</option>
|
||||||
|
option, or disabled altogether with the <option>--no-wait</option> option.
|
||||||
|
</para>
|
||||||
|
<note>
|
||||||
|
<para>
|
||||||
|
If PostgreSQL is not running on the local node, under some circumstances &repmgr; may not
|
||||||
|
be able to confirm if <application>repmgrd</application> has actually stopped.
|
||||||
|
</para>
|
||||||
|
</note>
|
||||||
|
|
||||||
|
<important>
|
||||||
|
<para>
|
||||||
|
The <filename>repmgr.conf</filename> parameter <varname>repmgrd_service_stop_command</varname>
|
||||||
|
must be set for <command>repmgr daemon stop</command> to work; see section
|
||||||
|
<xref linkend="repmgr-daemon-stop-configuration"> for details.
|
||||||
|
</para>
|
||||||
|
</important>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Configuration</title>
|
||||||
|
<para>
|
||||||
|
<command>repmgr daemon stop</command> will execute the command defined by the
|
||||||
|
<varname>repmgrd_service_stop_command</varname> parameter in <filename>repmgr.conf</filename>.
|
||||||
|
This must be set to a shell command which will stop <application>repmgrd</application>;
|
||||||
|
if &repmgr; was installed from a package, this will be the service command defined by the
|
||||||
|
package. For more details see <link linkend="appendix-packages">Appendix: &repmgr; package details</link>.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<important>
|
||||||
|
<para>
|
||||||
|
If &repmgr; was installed from a system package, and you do not configure
|
||||||
|
<varname>repmgrd_service_stop_command</varname> to an appropriate service command, this may
|
||||||
|
result in the system becoming confused about the state of the <application>repmgrd</application>
|
||||||
|
service; this is particularly the case with <literal>systemd</literal>.
|
||||||
|
</para>
|
||||||
|
</important>
|
||||||
|
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
|
||||||
|
<title>Options</title>
|
||||||
|
|
||||||
|
<variablelist>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--dry-run</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Check prerequisites but don't actually attempt to stop <application>repmgrd</application>.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
This action will output the command which would be executed.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>-w</option></term>
|
||||||
|
<term><option>--wait</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Wait for the specified number of seconds to confirm that <application>repmgrd</application>
|
||||||
|
stopped successfully.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Note that providing <option>--wait=0</option> is the equivalent of <option>--no-wait</option>.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--no-wait</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Don't wait to confirm that <application>repmgrd</application>
|
||||||
|
stopped successfully.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
This is equivalent to providing <option>--wait=0</option>.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1 id="repmgr-daemon-stop-configuration" xreflabel="repmgr daemon stop configuration">
|
||||||
|
<title>Configuration file settings</title>
|
||||||
|
<para>
|
||||||
|
The following parameter in <filename>repmgr.conf</filename> is relevant
|
||||||
|
to <command>repmgr daemon stop</command>:
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<variablelist>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<indexterm>
|
||||||
|
<primary>repmgrd_service_stop_command</primary>
|
||||||
|
<secondary>with "repmgr daemon stop"</secondary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<term><option>repmgrd_service_stop_command</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<command>repmgr daemon stop</command> will execute the command defined by the
|
||||||
|
<varname>repmgrd_service_stop_command</varname> parameter in <filename>repmgr.conf</filename>.
|
||||||
|
This must be set to a shell command which will stop <application>repmgrd</application>;
|
||||||
|
if &repmgr; was installed from a package, this will be the service command defined by the
|
||||||
|
package. For more details see <link linkend="appendix-packages">Appendix: &repmgr; package details</link>.
|
||||||
|
</para>
|
||||||
|
<important>
|
||||||
|
<para>
|
||||||
|
If &repmgr; was installed from a system package, and you do not configure
|
||||||
|
<varname>repmgrd_service_stop_command</varname> to an appropriate service command, this may
|
||||||
|
result in the system becoming confused about the state of the <application>repmgrd</application>
|
||||||
|
service; this is particularly the case with <literal>systemd</literal>.
|
||||||
|
</para>
|
||||||
|
</important>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Exit codes</title>
|
||||||
|
<para>
|
||||||
|
One of the following exit codes will be emitted by <command>repmgr daemon stop</command>:
|
||||||
|
</para>
|
||||||
|
<variablelist>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>SUCCESS (0)</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<application>repmgrd</application> could be stopped.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>ERR_BAD_CONFIG (1)</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<varname>repmgrd_service_stop_command</varname> is not defined in
|
||||||
|
<filename>repmgr.conf</filename>.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>ERR_REPMGRD_SERVICE (27)</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<application>repmgrd</application> could not be stopped.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
</variablelist>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>See also</title>
|
||||||
|
<para>
|
||||||
|
<xref linkend="repmgr-daemon-start">, <xref linkend="repmgr-daemon-status">, <xref linkend="repmgrd-daemon">
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
</refentry>
|
||||||
109
doc/repmgr-daemon-unpause.sgml
Normal file
109
doc/repmgr-daemon-unpause.sgml
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
<refentry id="repmgr-daemon-unpause">
|
||||||
|
<indexterm>
|
||||||
|
<primary>repmgr daemon unpause</primary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<indexterm>
|
||||||
|
<primary>repmgrd</primary>
|
||||||
|
<secondary>unpausing</secondary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
|
||||||
|
<refmeta>
|
||||||
|
<refentrytitle>repmgr daemon unpause</refentrytitle>
|
||||||
|
</refmeta>
|
||||||
|
|
||||||
|
<refnamediv>
|
||||||
|
<refname>repmgr daemon unpause</refname>
|
||||||
|
<refpurpose>Instruct all <application>repmgrd</application> instances in the replication cluster to resume failover operations</refpurpose>
|
||||||
|
</refnamediv>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Description</title>
|
||||||
|
<para>
|
||||||
|
This command can be run on any active node in the replication cluster to instruct all
|
||||||
|
running <application>repmgrd</application> instances to "unpause"
|
||||||
|
(following a previous execution of <xref linkend="repmgr-daemon-pause">)
|
||||||
|
and resume normal failover/monitoring operation.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<note>
|
||||||
|
<para>
|
||||||
|
It's important to wait a few seconds after restarting PostgreSQL on any node before running
|
||||||
|
<command>repmgr daemon pause</command>, as the <application>repmgrd</application> instance
|
||||||
|
on the restarted node will take a second or two before it has updated its status.
|
||||||
|
</para>
|
||||||
|
</note>
|
||||||
|
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Execution</title>
|
||||||
|
<para>
|
||||||
|
<command>repmgr daemon unpause</command> can be executed on any active node in the
|
||||||
|
replication cluster. A valid <filename>repmgr.conf</filename> file is required.
|
||||||
|
It will have no effect on nodes which are not already paused.
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Example</title>
|
||||||
|
<para>
|
||||||
|
<programlisting>
|
||||||
|
$ repmgr -f /etc/repmgr.conf daemon unpause
|
||||||
|
NOTICE: node 1 (node1) unpaused
|
||||||
|
NOTICE: node 2 (node2) unpaused
|
||||||
|
NOTICE: node 3 (node3) unpaused</programlisting>
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Options</title>
|
||||||
|
<variablelist>
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--dry-run</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Check if nodes are reachable but don't unpause <application>repmgrd</application>.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Exit codes</title>
|
||||||
|
<para>
|
||||||
|
One of the following exit codes will be emitted by <command>repmgr daemon unpause</command>:
|
||||||
|
</para>
|
||||||
|
<variablelist>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>SUCCESS (0)</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<application>repmgrd</application> could be unpaused on all nodes.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>ERR_REPMGRD_PAUSE (26)</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<application>repmgrd</application> could not be unpaused on one or mode nodes.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
</variablelist>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>See also</title>
|
||||||
|
<para>
|
||||||
|
<xref linkend="repmgr-daemon-pause">, <xref linkend="repmgr-daemon-status">
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
</refentry>
|
||||||
|
|
||||||
210
doc/repmgr-node-check.sgml
Normal file
210
doc/repmgr-node-check.sgml
Normal file
@@ -0,0 +1,210 @@
|
|||||||
|
<refentry id="repmgr-node-check">
|
||||||
|
<indexterm>
|
||||||
|
<primary>repmgr node check</primary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<refmeta>
|
||||||
|
<refentrytitle>repmgr node check</refentrytitle>
|
||||||
|
</refmeta>
|
||||||
|
|
||||||
|
<refnamediv>
|
||||||
|
<refname>repmgr node check</refname>
|
||||||
|
<refpurpose>performs some health checks on a node from a replication perspective</refpurpose>
|
||||||
|
</refnamediv>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Description</title>
|
||||||
|
<para>
|
||||||
|
Performs some health checks on a node from a replication perspective.
|
||||||
|
This command must be run on the local node.
|
||||||
|
</para>
|
||||||
|
<note>
|
||||||
|
<para>
|
||||||
|
Currently &repmgr; performs health checks on physical replication
|
||||||
|
slots only, with the aim of warning about streaming replication standbys which
|
||||||
|
have become detached and the associated risk of uncontrolled WAL file
|
||||||
|
growth.
|
||||||
|
</para>
|
||||||
|
</note>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Example</title>
|
||||||
|
<para>
|
||||||
|
<programlisting>
|
||||||
|
$ repmgr -f /etc/repmgr.conf node check
|
||||||
|
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 physical replication slots)
|
||||||
|
Missing replication slots: OK (node has no missing physical replication slots)</programlisting>
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
<refsect1>
|
||||||
|
<title>Individual checks</title>
|
||||||
|
<para>
|
||||||
|
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,
|
||||||
|
and returns <literal>WARNING</literal> or <literal>CRITICAL</literal> if the number
|
||||||
|
exceeds <varname>archive_ready_warning</varname> or <varname>archive_ready_critical</varname> respectively.
|
||||||
|
</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 physical replication slots
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
<literal>--missing-slots</literal>: checks there are no missing physical replication slots
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
<literal>--data-directory-config</literal>: checks the data directory configured in
|
||||||
|
<filename>repmgr.conf</filename> matches the actual data directory.
|
||||||
|
This check is not directly related to replication, but is useful to verify &repmgr;
|
||||||
|
is correctly configured.
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
|
||||||
|
</itemizedlist>
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Output format</title>
|
||||||
|
<para>
|
||||||
|
<itemizedlist spacing="compact" mark="bullet">
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
<literal>--csv</literal>: generate output in CSV format (not available
|
||||||
|
for individual checks)
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
<literal>--nagios</literal>: generate output in a Nagios-compatible format
|
||||||
|
(for individual checks only)
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Exit codes</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
When executing <command>repmgr node check</command> with one of the individual
|
||||||
|
checks listed above, &repmgr; will emit one of the following Nagios-style exit codes
|
||||||
|
(even if <literal>--nagios</literal> is not supplied):
|
||||||
|
|
||||||
|
<itemizedlist spacing="compact" mark="bullet">
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
<literal>0</literal>: OK
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
<literal>1</literal>: WARNING
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
<literal>2</literal>: ERROR
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
<literal>3</literal>: UNKNOWN
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
</itemizedlist>
|
||||||
|
</para>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<para>
|
||||||
|
One of the following exit codes will be emitted by <command>repmgr status check</command>
|
||||||
|
if no individual check was specified.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<variablelist>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>SUCCESS (0)</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
No issues were detected.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>ERR_NODE_STATUS (25)</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
One or more issues were detected.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
</variablelist>
|
||||||
|
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>See also</title>
|
||||||
|
<para>
|
||||||
|
<xref linkend="repmgr-node-status">, <xref linkend="repmgr-cluster-show">
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
</refentry>
|
||||||
387
doc/repmgr-node-rejoin.sgml
Normal file
387
doc/repmgr-node-rejoin.sgml
Normal file
@@ -0,0 +1,387 @@
|
|||||||
|
<refentry id="repmgr-node-rejoin">
|
||||||
|
|
||||||
|
<indexterm>
|
||||||
|
<primary>repmgr node rejoin</primary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<refmeta>
|
||||||
|
<refentrytitle>repmgr node rejoin</refentrytitle>
|
||||||
|
</refmeta>
|
||||||
|
|
||||||
|
<refnamediv>
|
||||||
|
<refname>repmgr node rejoin</refname>
|
||||||
|
<refpurpose>rejoin a dormant (stopped) node to the replication cluster</refpurpose>
|
||||||
|
</refnamediv>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Description</title>
|
||||||
|
<para>
|
||||||
|
Enables a dormant (stopped) node to be rejoined to the replication cluster.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
This can optionally use <application>pg_rewind</application> to re-integrate
|
||||||
|
a node which has diverged from the rest of the cluster, typically a failed primary.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<tip>
|
||||||
|
<para>
|
||||||
|
If the node is running and needs to be attached to the current primary, use
|
||||||
|
<xref linkend="repmgr-standby-follow">.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Note <xref linkend="repmgr-standby-follow"> can only be used for standbys which have not diverged
|
||||||
|
from the rest of the cluster.
|
||||||
|
</para>
|
||||||
|
</tip>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Usage</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
<programlisting>
|
||||||
|
repmgr node rejoin -d '$conninfo'</programlisting>
|
||||||
|
|
||||||
|
where <literal>$conninfo</literal> is the conninfo string of any reachable node in the cluster.
|
||||||
|
<filename>repmgr.conf</filename> for the stopped node *must* be supplied explicitly if not
|
||||||
|
otherwise available.
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
|
||||||
|
<title>Options</title>
|
||||||
|
<variablelist>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--dry-run</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Check prerequisites but don't actually execute the rejoin.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--force-rewind[=/path/to/pg_rewind]</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Execute <application>pg_rewind</application>.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
It is only necessary to provide the <application>pg_rewind</application> path
|
||||||
|
if using PostgreSQL 9.3 or 9.4, and <application>pg_rewind</application>
|
||||||
|
is not installed in the PostgreSQL <filename>bin</filename> directory.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--config-files</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
comma-separated list of configuration files to retain after
|
||||||
|
executing <application>pg_rewind</application>.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Currently <application>pg_rewind</application> will overwrite
|
||||||
|
the local node's configuration files with the files from the source node,
|
||||||
|
so it's advisable to use this option to ensure they are kept.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--config-archive-dir</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Directory to temporarily store configuration files specified with
|
||||||
|
<option>--config-files</option>; default: <filename>/tmp</filename>.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>-W/--no-wait</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Don't wait for the node to rejoin cluster.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
If this option is supplied, &repmgr; will restart the node but
|
||||||
|
not wait for it to connect to the primary.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
</variablelist>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Configuration file settings</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
<itemizedlist spacing="compact" mark="bullet">
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
<literal>node_rejoin_timeout</literal>:
|
||||||
|
the maximum length of time (in seconds) to wait for
|
||||||
|
the node to reconnect to the replication cluster (defaults to
|
||||||
|
the value set in <literal>standby_reconnect_timeout</literal>,
|
||||||
|
60 seconds).
|
||||||
|
</simpara>
|
||||||
|
<simpara>
|
||||||
|
Note that <literal>standby_reconnect_timeout</literal> must be
|
||||||
|
set to a value equal to or greater than
|
||||||
|
<literal>node_rejoin_timeout</literal>.
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
</para>
|
||||||
|
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1 id="repmgr-node-rejoin-events">
|
||||||
|
<title>Event notifications</title>
|
||||||
|
<para>
|
||||||
|
A <literal>node_rejoin</literal> <link linkend="event-notifications">event notification</link> will be generated.
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
<refsect1>
|
||||||
|
<title>Exit codes</title>
|
||||||
|
<para>
|
||||||
|
One of the following exit codes will be emitted by <command>repmgr node rejoin</command>:
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<variablelist>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>SUCCESS (0)</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
The node rejoin succeeded; or if <option>--dry-run</option> was provided,
|
||||||
|
no issues were detected which would prevent the node rejoin.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>ERR_BAD_CONFIG (1)</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
A configuration issue was detected which prevented &repmgr; from
|
||||||
|
continuing with the node rejoin.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>ERR_NO_RESTART (4)</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
The node could not be restarted.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>ERR_REJOIN_FAIL (24)</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
The node rejoin operation failed.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
</variablelist>
|
||||||
|
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Notes</title>
|
||||||
|
<para>
|
||||||
|
Currently <command>repmgr node rejoin</command> can only be used to attach
|
||||||
|
a standby to the current primary, not another standby.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The node must have been shut down cleanly; if this was not the case, it will
|
||||||
|
need to be manually started (remove any existing <filename>recovery.conf</filename> file first)
|
||||||
|
until it has reached a consistent recovery point, then shut down cleanly.
|
||||||
|
</para>
|
||||||
|
<tip>
|
||||||
|
<para>
|
||||||
|
If <application>PostgreSQL</application> is started in single-user mode and
|
||||||
|
input is directed from <filename>/dev/null/</filename>, it will perform recovery
|
||||||
|
then immediately quit, and will then be in a state suitable for use by
|
||||||
|
<application>pg_rewind</application>.
|
||||||
|
<programlisting>
|
||||||
|
rm -f /var/lib/pgsql/data/recovery.conf
|
||||||
|
postgres --single -D /var/lib/pgsql/data/ < /dev/null</programlisting>
|
||||||
|
</para>
|
||||||
|
</tip>
|
||||||
|
<para>
|
||||||
|
&repmgr; will attempt to verify whether the node can rejoin as-is, or whether
|
||||||
|
<command>pg_rewind</command> must be used (see following section).
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1 id="repmgr-node-rejoin-pg-rewind" xreflabel="Using pg_rewind">
|
||||||
|
|
||||||
|
<indexterm>
|
||||||
|
<primary>pg_rewind</primary>
|
||||||
|
<secondary>using with "repmgr node rejoin"</secondary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<title>Using <command>pg_rewind</command></title>
|
||||||
|
<para>
|
||||||
|
<command>repmgr node rejoin</command> 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.
|
||||||
|
<command>pg_rewind</command> is available in PostgreSQL 9.5 and later as part of the core distribution,
|
||||||
|
and can be installed from external sources for PostgreSQL 9.3 and 9.4.
|
||||||
|
</para>
|
||||||
|
<note>
|
||||||
|
<para>
|
||||||
|
<command>pg_rewind</command> <emphasis>requires</emphasis> 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/app-pgrewind.html"><command>pg_rewind</command> documentation</ulink> for details.
|
||||||
|
</para>
|
||||||
|
</note>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
We strongly recommend familiarizing yourself with <command>pg_rewind</command> before attempting
|
||||||
|
to use it with &repmgr;, as while it is an extremely useful tool, it is <emphasis>not</emphasis>
|
||||||
|
a "magic bullet" which can resolve all problematic replication situations.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
A typical use-case for <command>pg_rewind</command> is when a scenario like the following
|
||||||
|
is encountered:
|
||||||
|
<programlisting>
|
||||||
|
$ repmgr node rejoin -f /etc/repmgr.conf -d 'host=node3 dbname=repmgr user=repmgr' \
|
||||||
|
--force-rewind --config-files=postgresql.local.conf,postgresql.conf --verbose --dry-run
|
||||||
|
INFO: replication connection to the rejoin target node was successful
|
||||||
|
INFO: local and rejoin target system identifiers match
|
||||||
|
DETAIL: system identifier is 6652184002263212600
|
||||||
|
ERROR: this node cannot attach to rejoin target node 3
|
||||||
|
DETAIL: rejoin target server's timeline 2 forked off current database system timeline 1 before current recovery point 0/610D710
|
||||||
|
HINT: use --force-rewind to execute pg_rewind</programlisting>
|
||||||
|
|
||||||
|
Here, <literal>node3</literal> was promoted to a primary while the local node was
|
||||||
|
still attached to the previous primary; this can potentially happen during e.g. a
|
||||||
|
network split. <command>pg_rewind</command> can re-sync the local node with <literal>node3</literal>,
|
||||||
|
removing the need for a full reclone.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
To have <command>repmgr node rejoin</command> use <command>pg_rewind</command>,
|
||||||
|
pass the command line option <literal>--force-rewind</literal>, which will tell &repmgr;
|
||||||
|
to execute <command>pg_rewind</command> to ensure the node can be rejoined successfully.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<important>
|
||||||
|
<para>
|
||||||
|
Be aware that if <command>pg_rewind</command> is executed and actually performs a
|
||||||
|
rewind operation, any configuration files in the PostgreSQL data directory will be
|
||||||
|
overwritten with those from the source server.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
To prevent this happening, provide a comma-separated list of files to retain
|
||||||
|
using the <literal>--config-file</literal> command line option; the specified files
|
||||||
|
will be archived in a temporary directory (whose parent directory can be specified with
|
||||||
|
<literal>--config-archive-dir</literal>) and restored once the rewind operation is
|
||||||
|
complete.
|
||||||
|
</para>
|
||||||
|
</important>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Example, first using <literal>--dry-run</literal>, then actually executing the
|
||||||
|
<literal>node rejoin command</literal>.
|
||||||
|
<programlisting>
|
||||||
|
$ repmgr node rejoin -f /etc/repmgr.conf -d 'host=node3 dbname=repmgr user=repmgr' \
|
||||||
|
--config-files=postgresql.local.conf,postgresql.conf --verbose --force-rewind --dry-run
|
||||||
|
INFO: replication connection to the rejoin target node was successful
|
||||||
|
INFO: local and rejoin target system identifiers match
|
||||||
|
DETAIL: system identifier is 6652460429293670710
|
||||||
|
NOTICE: pg_rewind execution required for this node to attach to rejoin target node 3
|
||||||
|
DETAIL: rejoin target server's timeline 2 forked off current database system timeline 1 before current recovery point 0/610D710
|
||||||
|
INFO: prerequisites for using pg_rewind are met
|
||||||
|
INFO: file "postgresql.local.conf" would be copied to "/tmp/repmgr-config-archive-node2/postgresql.local.conf"
|
||||||
|
INFO: file "postgresql.replication-setup.conf" would be copied to "/tmp/repmgr-config-archive-node2/postgresql.replication-setup.conf"
|
||||||
|
INFO: pg_rewind would now be executed
|
||||||
|
DETAIL: pg_rewind command is:
|
||||||
|
pg_rewind -D '/var/lib/postgresql/data' --source-server='host=node3 dbname=repmgr user=repmgr'
|
||||||
|
INFO: prerequisites for executing NODE REJOIN are met</programlisting>
|
||||||
|
|
||||||
|
<note>
|
||||||
|
<para>
|
||||||
|
If <option>--force-rewind</option> is used with the <option>--dry-run</option> option,
|
||||||
|
this checks the prerequisites for using <application>pg_rewind</application>, but is
|
||||||
|
not an absolute guarantee that actually executing <application>pg_rewind</application>
|
||||||
|
will succeed. See also section <xref linkend="repmgr-node-rejoin-caveats"> below.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
</note>
|
||||||
|
|
||||||
|
<programlisting>
|
||||||
|
$ repmgr node rejoin -f /etc/repmgr.conf -d 'host=node3 dbname=repmgr user=repmgr' \
|
||||||
|
--config-files=postgresql.local.conf,postgresql.conf --verbose --force-rewind
|
||||||
|
NOTICE: pg_rewind execution required for this node to attach to rejoin target node 3
|
||||||
|
DETAIL: rejoin target server's timeline 2 forked off current database system timeline 1 before current recovery point 0/610D710
|
||||||
|
NOTICE: executing pg_rewind
|
||||||
|
DETAIL: pg_rewind command is "pg_rewind -D '/var/lib/postgresql/data' --source-server='host=node3 dbname=repmgr user=repmgr'"
|
||||||
|
NOTICE: 2 files copied to /var/lib/postgresql/data
|
||||||
|
NOTICE: setting node 2's upstream to node 3
|
||||||
|
NOTICE: starting server using "pg_ctl -l /var/log/postgres/startup.log -w -D '/var/lib/pgsql/data' start"
|
||||||
|
NOTICE: NODE REJOIN successful
|
||||||
|
DETAIL: node 2 is now attached to node 3</programlisting>
|
||||||
|
</para>
|
||||||
|
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1 id="repmgr-node-rejoin-caveats" xreflabel="Caveats">
|
||||||
|
|
||||||
|
<indexterm>
|
||||||
|
<primary>repmgr node rejoin</primary>
|
||||||
|
<secondary>caveats</secondary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<title>Caveats when using <command>repmgr node rejoin</command></title>
|
||||||
|
<para>
|
||||||
|
<command>repmgr node rejoin</command> attempts to determine whether it will succeed by
|
||||||
|
comparing the timelines and relative WAL positions of the local node (rejoin candidate) and primary
|
||||||
|
(rejoin target). This is particularly important if planning to use <application>pg_rewind</application>,
|
||||||
|
which currently (as of PostgreSQL 11) may appear to succeed (or indicate there is no action
|
||||||
|
needed) but potentially allow an impossible action, such as trying to rejoin a standby to a
|
||||||
|
primary which is behind the standby. &repmgr; will prevent this situation from occurring.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Currently it is <emphasis>not</emphasis> possible to detect a situation where the rejoin target
|
||||||
|
is a standby which has been "promoted" by removing <filename>recovery.conf</filename>
|
||||||
|
(PostgreSQL 12 and later: <filename>standby.signal</filename>) and restarting it.
|
||||||
|
In this case there will be no information about the point the rejoin target diverged
|
||||||
|
from the current standby; the rejoin operation will fail and
|
||||||
|
the current standby's PostgreSQL log will contain entries with the text
|
||||||
|
"<literal>record with incorrect prev-link</literal>".
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
We strongly recommend running <command>repmgr node rejoin</command> with the
|
||||||
|
<option>--dry-run</option> option first. Additionally it might be a good idea
|
||||||
|
to execute the <application>pg_rewind</application> command displayed by
|
||||||
|
&repmgr; with the <application>pg_rewind</application> <option>--dry-run</option>
|
||||||
|
option. Note that <application>pg_rewind</application> does not indicate that it
|
||||||
|
is running in <option>--dry-run</option> mode.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>See also</title>
|
||||||
|
<para>
|
||||||
|
<xref linkend="repmgr-standby-follow">
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
</refentry>
|
||||||
151
doc/repmgr-node-service.sgml
Normal file
151
doc/repmgr-node-service.sgml
Normal file
@@ -0,0 +1,151 @@
|
|||||||
|
<refentry id="repmgr-node-service">
|
||||||
|
<indexterm>
|
||||||
|
<primary>repmgr node service</primary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<refmeta>
|
||||||
|
<refentrytitle>repmgr node service</refentrytitle>
|
||||||
|
</refmeta>
|
||||||
|
|
||||||
|
<refnamediv>
|
||||||
|
<refname>repmgr node service</refname>
|
||||||
|
<refpurpose>show or execute the system service command to stop/start/restart/reload/promote a node</refpurpose>
|
||||||
|
</refnamediv>
|
||||||
|
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Description</title>
|
||||||
|
<para>
|
||||||
|
Shows or executes the system service command to stop/start/restart/reload a node.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
This command is mainly meant for internal &repmgr; usage, but is useful for
|
||||||
|
confirming the command configuration.
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
|
||||||
|
<title>Options</title>
|
||||||
|
|
||||||
|
<variablelist>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--dry-run</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Log the steps which would be taken, including displaying the command which would be executed.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--action</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
The action to perform. One of <literal>start</literal>, <literal>stop</literal>,
|
||||||
|
<literal>restart</literal>, <literal>reload</literal> or <literal>promote</literal>.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
If the parameter <option>--list-actions</option> is provided together with
|
||||||
|
<option>--action</option>, the command which would be executed will be printed.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--list-actions</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
List all configured commands.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
If the parameter <option>--action</option> is provided together with
|
||||||
|
<option>--list-actions</option>, the command which would be executed for that
|
||||||
|
particular action will be printed.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--checkpoint</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Issue a <command>CHECKPOINT</command> before stopping or restarting the node.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Exit codes</title>
|
||||||
|
<para>
|
||||||
|
One of the following exit codes will be emitted by <command>repmgr node service</command>:
|
||||||
|
</para>
|
||||||
|
<variablelist>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>SUCCESS (0)</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
No issues were detected.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>ERR_LOCAL_COMMAND (5)</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Execution of the system service command failed.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
</variablelist>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Examples</title>
|
||||||
|
<para>
|
||||||
|
See what action would be taken for a restart:
|
||||||
|
<programlisting>
|
||||||
|
[postgres@node1 ~]$ repmgr -f /etc/repmgr/11/repmgr.conf node service --action=restart --checkpoint --dry-run
|
||||||
|
INFO: a CHECKPOINT would be issued here
|
||||||
|
INFO: would execute server command "sudo service postgresql-11 restart"</programlisting>
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Restart the PostgreSQL instance:
|
||||||
|
<programlisting>
|
||||||
|
[postgres@node1 ~]$ repmgr -f /etc/repmgr/11/repmgr.conf node service --action=restart --checkpoint
|
||||||
|
NOTICE: issuing CHECKPOINT
|
||||||
|
DETAIL: executing server command "sudo service postgresql-11 restart"
|
||||||
|
Redirecting to /bin/systemctl restart postgresql-11.service</programlisting>
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
List all commands:
|
||||||
|
<programlisting>
|
||||||
|
[postgres@node1 ~]$ repmgr -f /etc/repmgr/11/repmgr.conf node service --list-actions
|
||||||
|
Following commands would be executed for each action:
|
||||||
|
|
||||||
|
start: "sudo service postgresql-11 start"
|
||||||
|
stop: "sudo service postgresql-11 stop"
|
||||||
|
restart: "sudo service postgresql-11 restart"
|
||||||
|
reload: "sudo service postgresql-11 reload"
|
||||||
|
promote: "/usr/pgsql-11/bin/pg_ctl -w -D '/var/lib/pgsql/11/data' promote"</programlisting>
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
List a single command:
|
||||||
|
<programlisting>
|
||||||
|
[postgres@node1 ~]$ repmgr -f /etc/repmgr/11/repmgr.conf node service --list-actions --action=promote
|
||||||
|
/usr/pgsql-11/bin/pg_ctl -w -D '/var/lib/pgsql/11/data' promote </programlisting>
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
</refentry>
|
||||||
91
doc/repmgr-node-status.sgml
Normal file
91
doc/repmgr-node-status.sgml
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
<refentry id="repmgr-node-status">
|
||||||
|
<indexterm>
|
||||||
|
<primary>repmgr node status</primary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<refmeta>
|
||||||
|
<refentrytitle>repmgr node status</refentrytitle>
|
||||||
|
</refmeta>
|
||||||
|
|
||||||
|
<refnamediv>
|
||||||
|
<refname>repmgr node status</refname>
|
||||||
|
<refpurpose>show overview of a node's basic information and replication status</refpurpose>
|
||||||
|
</refnamediv>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Description</title>
|
||||||
|
<para>
|
||||||
|
Displays an overview of a node's basic information and replication
|
||||||
|
status. This command must be run on the local node.
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Example</title>
|
||||||
|
<para>
|
||||||
|
<programlisting>
|
||||||
|
$ repmgr -f /etc/repmgr.conf node status
|
||||||
|
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>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Output format</title>
|
||||||
|
<para>
|
||||||
|
<itemizedlist spacing="compact" mark="bullet">
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
<literal>--csv</literal>: generate output in CSV format
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Exit codes</title>
|
||||||
|
<para>
|
||||||
|
One of the following exit codes will be emitted by <command>repmgr node status</command>:
|
||||||
|
</para>
|
||||||
|
<variablelist>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>SUCCESS (0)</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
No issues were detected.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>ERR_NODE_STATUS (25)</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
One or more issues were detected.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
</variablelist>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>See also</title>
|
||||||
|
<para>
|
||||||
|
See <xref linkend="repmgr-node-check"> to diagnose issues and <xref linkend="repmgr-cluster-show">
|
||||||
|
for an overview of all nodes in the cluster.
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
</refentry>
|
||||||
102
doc/repmgr-primary-register.sgml
Normal file
102
doc/repmgr-primary-register.sgml
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
<refentry id="repmgr-primary-register">
|
||||||
|
<indexterm>
|
||||||
|
<primary>repmgr primary register</primary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<refmeta>
|
||||||
|
<refentrytitle>repmgr primary register</refentrytitle>
|
||||||
|
</refmeta>
|
||||||
|
|
||||||
|
<refnamediv>
|
||||||
|
<refname>repmgr primary register</refname>
|
||||||
|
<refpurpose>initialise a repmgr installation and register the primary node</refpurpose>
|
||||||
|
</refnamediv>
|
||||||
|
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Description</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>
|
||||||
|
|
||||||
|
<note>
|
||||||
|
<para>
|
||||||
|
It's possibly to install the &repmgr; extension manually before executing
|
||||||
|
<command>repmgr primary register</command>; in this case &repmgr; will
|
||||||
|
detect the presence of the extension and skip that step.
|
||||||
|
</para>
|
||||||
|
</note>
|
||||||
|
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Execution</title>
|
||||||
|
<para>
|
||||||
|
Execute with the <option>--dry-run</option> 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>
|
||||||
|
|
||||||
|
<note>
|
||||||
|
<para>
|
||||||
|
If providing the configuration file location with <option>-f/--config-file</option>,
|
||||||
|
avoid using a relative path, as &repmgr; stores the configuration file location
|
||||||
|
in the repmgr metadata for use when &repmgr; is executed remotely (e.g. during
|
||||||
|
<xref linkend="repmgr-standby-switchover">). &repmgr; will attempt to convert the
|
||||||
|
a relative path into an absolute one, but this may not be the same as the path you
|
||||||
|
would explicitly provide (e.g. <filename>./repmgr.conf</filename> might be converted
|
||||||
|
to <filename>/path/to/./repmgr.conf</filename>, whereas you'd normally write
|
||||||
|
<filename>/path/to/repmgr.conf</filename>).
|
||||||
|
</para>
|
||||||
|
</note>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
|
||||||
|
<title>Options</title>
|
||||||
|
<variablelist>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--dry-run</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Check prerequisites but don't actually register the primary.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>-F</option>, <option>--force</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Overwrite an existing node record
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
</variablelist>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
|
||||||
|
<refsect1 id="repmgr-primary-register-events">
|
||||||
|
<title>Event notifications</title>
|
||||||
|
<para>
|
||||||
|
Following <link linkend="event-notifications">event notifications</link> will be generated:
|
||||||
|
<itemizedlist spacing="compact" mark="bullet">
|
||||||
|
<listitem>
|
||||||
|
<simpara><literal>cluster_created</literal></simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara><literal>primary_register</literal></simpara>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
</refentry>
|
||||||
74
doc/repmgr-primary-unregister.sgml
Normal file
74
doc/repmgr-primary-unregister.sgml
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
<refentry id="repmgr-primary-unregister">
|
||||||
|
<indexterm>
|
||||||
|
<primary>repmgr primary unregister</primary>
|
||||||
|
</indexterm>
|
||||||
|
<refmeta>
|
||||||
|
<refentrytitle>repmgr primary unregister</refentrytitle>
|
||||||
|
</refmeta>
|
||||||
|
<refnamediv>
|
||||||
|
<refname>repmgr primary unregister</refname>
|
||||||
|
<refpurpose>unregister an inactive primary node</refpurpose>
|
||||||
|
</refnamediv>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Description</title>
|
||||||
|
<para>
|
||||||
|
<command>repmgr primary unregister</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>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Execution</title>
|
||||||
|
<para>
|
||||||
|
<command>repmgr primary unregister</command> can be run on any active &repmgr; node,
|
||||||
|
with the ID of the node to unregister passed as <option>--node-id</option>.
|
||||||
|
</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>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
|
||||||
|
<title>Options</title>
|
||||||
|
|
||||||
|
<variablelist>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--dry-run</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Check prerequisites but don't actually unregister the primary.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--node-id</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
ID of the inactive primary to be unregistered.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
</variablelist>
|
||||||
|
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1 id="repmgr-primary-unregister-events">
|
||||||
|
<title>Event notifications</title>
|
||||||
|
<para>
|
||||||
|
A <literal>primary_unregister</literal> <link linkend="event-notifications">event notification</link> will be generated.
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
</refentry>
|
||||||
368
doc/repmgr-standby-clone.sgml
Normal file
368
doc/repmgr-standby-clone.sgml
Normal file
@@ -0,0 +1,368 @@
|
|||||||
|
<refentry id="repmgr-standby-clone">
|
||||||
|
<indexterm>
|
||||||
|
<primary>repmgr standby clone</primary>
|
||||||
|
<seealso>cloning</seealso>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<refmeta>
|
||||||
|
<refentrytitle>repmgr standby clone</refentrytitle>
|
||||||
|
</refmeta>
|
||||||
|
|
||||||
|
<refnamediv>
|
||||||
|
<refname>repmgr standby clone</refname>
|
||||||
|
<refpurpose>clone a PostgreSQL standby node from another PostgreSQL node</refpurpose>
|
||||||
|
</refnamediv>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Description</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
|
||||||
|
a standby, the command <command>repmgr standby register</command> must be executed to
|
||||||
|
notify &repmgr; of its existence.
|
||||||
|
</simpara>
|
||||||
|
</note>
|
||||||
|
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
|
||||||
|
<refsect1 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 <option>--copy-external-config-files</option>
|
||||||
|
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>
|
||||||
|
|
||||||
|
<note>
|
||||||
|
<para>
|
||||||
|
When executing <command>repmgr standby clone</command> with the
|
||||||
|
<option>--copy-external-config-files</option> aand <option>--dry-run</option>
|
||||||
|
options, &repmgr; will check the SSH connection to the source node, but
|
||||||
|
will not verify whether the files can actually be copied.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
During the actual clone operation, a check will be made before the database itself
|
||||||
|
is cloned to determine whether the files can actually be copied; if any problems are
|
||||||
|
encountered, the clone operation will be aborted, enabling the user to fix
|
||||||
|
any issues before retrying the clone operation.
|
||||||
|
</para>
|
||||||
|
</note>
|
||||||
|
|
||||||
|
<tip>
|
||||||
|
<simpara>
|
||||||
|
For reliable configuration file management we recommend using a
|
||||||
|
configuration management tool such as Ansible, Chef, Puppet or Salt.
|
||||||
|
</simpara>
|
||||||
|
</tip>
|
||||||
|
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1 id="repmgr-standby-clone-recovery-conf">
|
||||||
|
<indexterm>
|
||||||
|
<primary>recovery.conf</primary>
|
||||||
|
<secondary>customising with "repmgr standby clone"</secondary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<title>Customising recovery.conf</title>
|
||||||
|
<para>
|
||||||
|
By default, &repmgr; will create a minimal <filename>recovery.conf</filename>
|
||||||
|
containing following parameters:
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<itemizedlist spacing="compact" mark="bullet">
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara><varname>standby_mode</varname> (always <literal>'on'</literal>)</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara><varname>recovery_target_timeline</varname> (always <literal>'latest'</literal>)</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara><varname>primary_conninfo</varname></simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara><varname>primary_slot_name</varname> (if replication slots in use)</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
</itemizedlist>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
The following additional parameters can be specified in <filename>repmgr.conf</filename>
|
||||||
|
for inclusion in <filename>recovery.conf</filename>:
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<itemizedlist spacing="compact" mark="bullet">
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara><varname>restore_command</varname></simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara><varname>archive_cleanup_command</varname></simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara><varname>recovery_min_apply_delay</varname></simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
</itemizedlist>
|
||||||
|
|
||||||
|
<note>
|
||||||
|
<para>
|
||||||
|
We recommend using <ulink url="https://www.pgbarman.org/">Barman</ulink> to manage
|
||||||
|
WAL file archiving. For more details on combining &repmgr; and <application>Barman</application>,
|
||||||
|
in particular using <varname>restore_command</varname> to configure Barman as a backup source of
|
||||||
|
WAL files, see <xref linkend="cloning-from-barman">.
|
||||||
|
</para>
|
||||||
|
</note>
|
||||||
|
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1 id="repmgr-standby-clone-wal-management">
|
||||||
|
<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 <command>pg_basebackup</command> 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/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>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
|
||||||
|
<refsect1 id="repmgr-standby-create-recovery-conf">
|
||||||
|
|
||||||
|
<indexterm>
|
||||||
|
<primary>recovery.conf</primary>
|
||||||
|
<secondary>generating for a standby cloned by another method</secondary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<title>Using a standby cloned by another method</title>
|
||||||
|
<para>
|
||||||
|
&repmgr; supports standbys cloned by another method (e.g. using <application>barman</application>'s
|
||||||
|
<command><ulink url="http://docs.pgbarman.org/release/2.5/#recover">barman recover</ulink></command> command).
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
To integrate the standby as a &repmgr; node, once the standby has been cloned,
|
||||||
|
ensure the <filename>repmgr.conf</filename>
|
||||||
|
file is created for the node, and that it has been registered using
|
||||||
|
<command><link linkend="repmgr-standby-register">repmgr standby register</link></command>.
|
||||||
|
Then execute the command <command>repmgr standby clone --recovery-conf-only</command>.
|
||||||
|
This will create the <filename>recovery.conf</filename> file needed to attach
|
||||||
|
the node to its upstream, and will also create a replication slot on the
|
||||||
|
upstream node if required.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Note that the upstream node must be running. An existing
|
||||||
|
<filename>recovery.conf</filename> will not be overwritten unless the
|
||||||
|
<option>-F/--force</option> option is provided.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Execute <command>repmgr standby clone --recovery-conf-only --dry-run</command>
|
||||||
|
to check the prerequisites for creating the <filename>recovery.conf</filename> file,
|
||||||
|
and display the contents of the file without actually creating it.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<note>
|
||||||
|
<para>
|
||||||
|
<option>--recovery-conf-only</option> was introduced in &repmgr; <link linkend="release-4.0.4">4.0.4</link>.
|
||||||
|
</para>
|
||||||
|
</note>
|
||||||
|
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
|
||||||
|
<title>Options</title>
|
||||||
|
|
||||||
|
<variablelist>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>-d, --dbname=CONNINFO</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Connection string of the upstream node to use for cloning.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--dry-run</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Check prerequisites but don't actually clone the standby.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
If <option>--recovery-conf-only</option> specified, the contents of
|
||||||
|
the generated <filename>recovery.conf</filename> file will be displayed
|
||||||
|
but the file itself not written.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>-c, --fast-checkpoint</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Force fast checkpoint (not effective when cloning from Barman).
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--copy-external-config-files[={samepath|pgdata}]</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Copy configuration files located outside the data directory on the source
|
||||||
|
node to the same path on the standby (default) or to the
|
||||||
|
PostgreSQL data directory.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--no-upstream-connection</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
When using Barman, do not connect to upstream node.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>-R, --remote-user=USERNAME</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Remote system username for SSH operations (default: current local system username).
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option> --recovery-conf-only</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Create <filename>recovery.conf</filename> file for a previously cloned instance. &repmgr 4.0.4 and later.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--replication-user</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
User to make replication connections with (optional, not usually required).
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--superuser</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
If the &repmgr; user is not a superuser, the name of a valid superuser must
|
||||||
|
be provided with this option.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--upstream-conninfo</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<literal>primary_conninfo</literal> value to write in recovery.conf
|
||||||
|
when the intended upstream server does not yet exist.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--upstream-node-id</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
ID of the upstream node to replicate from (optional, defaults to primary node)
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--without-barman </option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Do not use Barman even if configured.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
</variablelist>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1 id="repmgr-standby-clone-events">
|
||||||
|
<title>Event notifications</title>
|
||||||
|
<para>
|
||||||
|
A <literal>standby_clone</literal> <link linkend="event-notifications">event notification</link> will be generated.
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>See also</title>
|
||||||
|
<para>
|
||||||
|
See <xref linkend="cloning-standbys"> for details about various aspects of cloning.
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
</refentry>
|
||||||
|
|
||||||
258
doc/repmgr-standby-follow.sgml
Normal file
258
doc/repmgr-standby-follow.sgml
Normal file
@@ -0,0 +1,258 @@
|
|||||||
|
<refentry id="repmgr-standby-follow">
|
||||||
|
<indexterm>
|
||||||
|
<primary>repmgr standby follow</primary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<refmeta>
|
||||||
|
<refentrytitle>repmgr standby follow</refentrytitle>
|
||||||
|
</refmeta>
|
||||||
|
|
||||||
|
<refnamediv>
|
||||||
|
<refname>repmgr standby follow</refname>
|
||||||
|
<refpurpose>attach a running standby to a new upstream node</refpurpose>
|
||||||
|
</refnamediv>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Description</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Attaches the standby ("follow candidate") to a new upstream node
|
||||||
|
("follow target"). Typically this will be the primary, but this
|
||||||
|
command can also be used to attach the standby to another standby.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
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>
|
||||||
|
By default &repmgr; will attempt to attach the standby to the current primary.
|
||||||
|
If <option>--upstream-node-id</option> is provided, &repmgr; will attempt
|
||||||
|
to attach the standby to the specified node, which can be another standby.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
This command will force a restart of the standby server, which must be
|
||||||
|
running.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<tip>
|
||||||
|
<para>
|
||||||
|
To re-add an inactive node to the replication cluster, use
|
||||||
|
<xref linkend="repmgr-node-rejoin">.
|
||||||
|
</para>
|
||||||
|
</tip>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
<command>repmgr standby follow</command> will wait up to
|
||||||
|
<varname>standby_follow_timeout</varname> seconds (default: <literal>30</literal>)
|
||||||
|
to verify the standby has actually connected to the new upstream node.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<note>
|
||||||
|
<para>
|
||||||
|
If <option>recovery_min_apply_delay</option> is set for the standby, it
|
||||||
|
will not attach to the new upstream node until it has replayed available
|
||||||
|
WAL.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Conversely, if the standby is attached to an upstream standby
|
||||||
|
which has <option>recovery_min_apply_delay</option> set, the upstream
|
||||||
|
standby's replay state may actually be behind that of its new downstream node.
|
||||||
|
</para>
|
||||||
|
</note>
|
||||||
|
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Example</title>
|
||||||
|
<para>
|
||||||
|
<programlisting>
|
||||||
|
$ repmgr -f /etc/repmgr.conf standby follow
|
||||||
|
INFO: setting node 3's primary to node 2
|
||||||
|
NOTICE: restarting server using "pg_ctl -l /var/log/postgres/startup.log -w -D '/var/lib/postgres/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>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Options</title>
|
||||||
|
<variablelist>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--dry-run</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Check prerequisites but don't actually follow a new upstream node.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
This will also verify whether the standby is capable of following the new upstream node.
|
||||||
|
</para>
|
||||||
|
<important>
|
||||||
|
<para>
|
||||||
|
If a standby was turned into a primary by removing <filename>recovery.conf</filename>
|
||||||
|
(<application>PostgreSQL 12</application> and later: <filename>standby.signal</filename>),
|
||||||
|
&repmgr; will <emphasis>not</emphasis> be able to determine whether that primary's timeline
|
||||||
|
has diverged from the timeline of the standby ("follow candidate").
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
We recommend always to use <link linkend="repmgr-standby-promote"><command>repmgr standby promote</command></link>
|
||||||
|
to promote a standby to primary, as this will ensure that the new primary
|
||||||
|
will perform a timeline switch (making it practical to check for timeline divergence)
|
||||||
|
and also that &repmgr; metadata is updated correctly.
|
||||||
|
</para>
|
||||||
|
</important>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--upstream-node-id</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Node ID of the new upstream node ("follow target").
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
If not provided, &repmgr; will attempt to follow the current primary node.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Note that when using <application>repmgrd</application>, <option>--upstream-node-id</option>
|
||||||
|
should always be configured;
|
||||||
|
see <link linkend="repmgrd-automatic-failover-configuration">Automatic failover configuration</link>
|
||||||
|
for details.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>-w</option></term>
|
||||||
|
<term><option>--wait</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Wait for a primary to appear. &repmgr; will wait for up to
|
||||||
|
<varname>primary_follow_timeout</varname> seconds
|
||||||
|
(default: 60 seconds) to verify that the standby is following the new primary.
|
||||||
|
This value can be defined in <filename>repmgr.conf</filename>.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
</variablelist>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Execution</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Execute with the <literal>--dry-run</literal> option to test the follow operation as
|
||||||
|
far as possible, without actually changing the status of the node.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Note that &repmgr; will first attempt to determine whether the standby
|
||||||
|
("follow candidate") is capable of following the
|
||||||
|
new upstream node ("follow target").
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
If, for example, the new upstream node has diverged from this node's timeline,
|
||||||
|
for example if the new upstream node was promoted to primary while this node
|
||||||
|
was still attached to the original primary, it will <emphasis>not</emphasis>
|
||||||
|
be possible to follow the new upstream node, and &repmgr; will emit an error
|
||||||
|
message like this:
|
||||||
|
<programlisting>
|
||||||
|
ERROR: this node cannot attach to follow target node 3
|
||||||
|
DETAIL: follow target server's timeline 2 forked off current database system timeline 1 before current recovery point 0/6108880</programlisting>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
In this case, it may be possible to have this node follow the new upstream
|
||||||
|
using <command><link linkend="repmgr-node-rejoin">repmgr node rejoin</link></command>
|
||||||
|
with the <option>--force-rewind</option> to execute <command>pg_rewind</command>.
|
||||||
|
This does mean that transactions which exist on this node, but not the new upstream,
|
||||||
|
will be lost.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Exit codes</title>
|
||||||
|
<para>
|
||||||
|
One of the following exit codes will be emitted by <command>repmgr standby follow</command>:
|
||||||
|
</para>
|
||||||
|
<variablelist>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>SUCCESS (0)</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
The follow operation succeeded; or if <option>--dry-run</option> was provided,
|
||||||
|
no issues were detected which would prevent the follow operation.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>ERR_BAD_CONFIG (1)</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
A configuration issue was detected which prevented &repmgr; from
|
||||||
|
continuing with the follow operation.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>ERR_NO_RESTART (4)</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
The node could not be restarted.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>ERR_DB_CONN (6)</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
&repmgr; was unable to establish a database connection to one of the nodes.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>ERR_FOLLOW_FAIL (23)</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
&repmgr; was unable to complete the follow command.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
</variablelist>
|
||||||
|
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1 id="repmgr-standby-follow-events">
|
||||||
|
<title>Event notifications</title>
|
||||||
|
<para>
|
||||||
|
A <literal>standby_follow</literal> <link linkend="event-notifications">event notification</link> will be generated.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
If provided, &repmgr; will substitute the placeholders <literal>%p</literal> with the node ID of the node
|
||||||
|
being followed, <literal>%c</literal> with its <literal>conninfo</literal> string, and
|
||||||
|
<literal>%a</literal> with its node name.
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>See also</title>
|
||||||
|
<para>
|
||||||
|
<xref linkend="repmgr-node-rejoin">
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
</refentry>
|
||||||
199
doc/repmgr-standby-promote.sgml
Normal file
199
doc/repmgr-standby-promote.sgml
Normal file
@@ -0,0 +1,199 @@
|
|||||||
|
<refentry id="repmgr-standby-promote">
|
||||||
|
<indexterm>
|
||||||
|
<primary>repmgr standby promote</primary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<refmeta>
|
||||||
|
<refentrytitle>repmgr standby promote</refentrytitle>
|
||||||
|
</refmeta>
|
||||||
|
|
||||||
|
<refnamediv>
|
||||||
|
<refname>repmgr standby promote</refname>
|
||||||
|
<refpurpose>promote a standby to a primary</refpurpose>
|
||||||
|
</refnamediv>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Description</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 <application>repmgrd</application>
|
||||||
|
is active, it will handle this automatically.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Note that &repmgr; will wait for up to <varname>promote_check_timeout</varname> seconds
|
||||||
|
(default: 60 seconds) to verify that the standby has been promoted, and will
|
||||||
|
check the promotion every <varname>promote_check_interval</varname> seconds (default: 1 second).
|
||||||
|
Both values can be defined in <filename>repmgr.conf</filename>.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<note>
|
||||||
|
<para>
|
||||||
|
If WAL replay is paused on the standby, and not all WAL files on the standby have been
|
||||||
|
replayed, &repmgr; will not attempt to promote it.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
This is because if WAL replay is paused, PostgreSQL itself will not react to a promote command
|
||||||
|
until WAL replay is resumed and all pending WAL has been replayed. This means
|
||||||
|
attempting to promote PostgreSQL in this state will leave PostgreSQL in a condition where the
|
||||||
|
promotion may occur at a unpredictable point in the future.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Note that if the standby is in archive recovery, &repmgr; will not be able to determine
|
||||||
|
if more WAL is pending replay, and will abort the promotion attempt if WAL replay is paused.
|
||||||
|
</para>
|
||||||
|
</note>
|
||||||
|
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Example</title>
|
||||||
|
<para>
|
||||||
|
<programlisting>
|
||||||
|
$ repmgr -f /etc/repmgr.conf standby promote
|
||||||
|
NOTICE: promoting standby to primary
|
||||||
|
DETAIL: promoting server "node2" (ID: 2) using "pg_ctl -l /var/log/postgres/startup.log -w -D '/var/lib/postgres/data' promote"
|
||||||
|
server promoting
|
||||||
|
DEBUG: setting node 2 as primary and marking existing primary as failed
|
||||||
|
NOTICE: STANDBY PROMOTE successful
|
||||||
|
DETAIL: server "node2" (ID: 2) was successfully promoted to primary</programlisting>
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Options</title>
|
||||||
|
<variablelist>
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--dry-run</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Check if this node can be promoted, but don't carry out the promotion
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Configuration file settings</title>
|
||||||
|
<para>
|
||||||
|
The following parameters in <filename>repmgr.conf</filename> are relevant to the
|
||||||
|
promote operation:
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
<itemizedlist spacing="compact" mark="bullet">
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<indexterm>
|
||||||
|
<primary>promote_check_interval</primary>
|
||||||
|
<secondary>with "repmgr standby promote "</secondary>
|
||||||
|
</indexterm>
|
||||||
|
<simpara>
|
||||||
|
<literal>promote_check_interval</literal>:
|
||||||
|
interval (in seconds, default: 1 second) to wait between each check
|
||||||
|
to determine whether the standby has been promoted.
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<indexterm>
|
||||||
|
<primary>promote_check_timeout</primary>
|
||||||
|
<secondary>with "repmgr standby promote "</secondary>
|
||||||
|
</indexterm>
|
||||||
|
<simpara>
|
||||||
|
<literal>promote_check_timeout</literal>:
|
||||||
|
time (in seconds, default: 60 seconds) to wait to verify that the standby has been promoted
|
||||||
|
before exiting with <literal>ERR_PROMOTION_FAIL</literal>.
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
</itemizedlist>
|
||||||
|
</para>
|
||||||
|
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Exit codes</title>
|
||||||
|
<para>
|
||||||
|
Following exit codes can be emitted by <command>repmgr standby promote</command>:
|
||||||
|
</para>
|
||||||
|
<variablelist>
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>SUCCESS (0)</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
The standby was successfully promoted to primary.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>ERR_DB_CONN (6)</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
&repmgr; was unable to connect to the local PostgreSQL node.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
PostgreSQL must be running before the node can be promoted.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>ERR_PROMOTION_FAIL (8)</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
The node could not be promoted to primary for one of the following
|
||||||
|
reasons:
|
||||||
|
<itemizedlist spacing="compact" mark="bullet">
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
there is an existing primary node in the replication cluster
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
the node is not a standby
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
WAL replay is paused on the node
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
execution of the PostgreSQL promote command failed
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
</itemizedlist>
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
</variablelist>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
|
||||||
|
<refsect1 id="repmgr-standby-promote-events">
|
||||||
|
<title>Event notifications</title>
|
||||||
|
<para>
|
||||||
|
A <literal>standby_promote</literal> <link linkend="event-notifications">event notification</link> will be generated.
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
</refentry>
|
||||||
183
doc/repmgr-standby-register.sgml
Normal file
183
doc/repmgr-standby-register.sgml
Normal file
@@ -0,0 +1,183 @@
|
|||||||
|
<refentry id="repmgr-standby-register" xreflabel="repmgr standby register">
|
||||||
|
<indexterm>
|
||||||
|
<primary>repmgr standby register</primary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<refmeta>
|
||||||
|
<refentrytitle>repmgr standby register</refentrytitle>
|
||||||
|
</refmeta>
|
||||||
|
|
||||||
|
<refnamediv>
|
||||||
|
<refname>repmgr standby register</refname>
|
||||||
|
<refpurpose>add a standby's information to the &repmgr; metadata</refpurpose>
|
||||||
|
</refnamediv>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Description</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 <application>repmgrd</application> 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>
|
||||||
|
|
||||||
|
<note>
|
||||||
|
<para>
|
||||||
|
If providing the configuration file location with <literal>-f/--config-file</literal>,
|
||||||
|
avoid using a relative path, as &repmgr; stores the configuration file location
|
||||||
|
in the repmgr metadata for use when &repmgr; is executed remotely (e.g. during
|
||||||
|
<xref linkend="repmgr-standby-switchover">). &repmgr; will attempt to convert the
|
||||||
|
a relative path into an absolute one, but this may not be the same as the path you
|
||||||
|
would explicitly provide (e.g. <filename>./repmgr.conf</filename> might be converted
|
||||||
|
to <filename>/path/to/./repmgr.conf</filename>, whereas you'd normally write
|
||||||
|
<filename>/path/to/repmgr.conf</filename>).
|
||||||
|
</para>
|
||||||
|
</note>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1 id="repmgr-standby-register-wait-start" xreflabel="repmgr standby register --wait-start">
|
||||||
|
<title>Waiting for the the standby to start</title>
|
||||||
|
<para>
|
||||||
|
By default, &repmgr; will wait 30 seconds for the standby to become available before
|
||||||
|
aborting with a connection error. This is useful when setting up a standby from a script,
|
||||||
|
as the standby may not have fully started up by the time <command>repmgr standby register</command>
|
||||||
|
is executed.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
To change the timeout, pass the desired value with the <literal>--wait-start</literal> option.
|
||||||
|
A value of <literal>0</literal> will disable the timeout.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The timeout will be ignored if <literal>-F/--force</literal> was provided.
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1 id="repmgr-standby-register-wait-sync" xreflabel="repmgr standby register --wait-sync">
|
||||||
|
<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
|
||||||
|
<application>repmgrd</application>) require that the standby's node record
|
||||||
|
is present and up-to-date to function correctly.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
By providing the option <option>--wait-sync</option> 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. <option>--wait-sync=60</option>).
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1 id="repmgr-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 <option>-F/--force</option>
|
||||||
|
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 <option>-F/--force</option> will result in the creation of an inactive placeholder
|
||||||
|
record for the upstream node, which will however later need to be registered
|
||||||
|
with the <option>-F/--force</option> option too.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
When used with <command>repmgr standby register</command>, care should be taken that use of the
|
||||||
|
<option>-F/--force</option> option does not result in an incorrectly configured cluster.
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1 id="repmgr-standby-register-node-cloned-other-source">
|
||||||
|
<title>Registering a node not cloned by repmgr</title>
|
||||||
|
<para>
|
||||||
|
If you've cloned a standby using another method (e.g. <application>barman</application>'s
|
||||||
|
<command>barman recover</command> command), first execute
|
||||||
|
<link linkend="repmgr-standby-create-recovery-conf">repmgr standby clone --recovery-conf-only</link>
|
||||||
|
to add the <filename>recovery.conf</filename> file, then register the standby as usual.
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
|
||||||
|
<title>Options</title>
|
||||||
|
|
||||||
|
<variablelist>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--dry-run</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Check prerequisites but don't actually register the standby.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>-F</option><option>--force</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Overwrite an existing node record
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--upstream-node-id</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
ID of the upstream node to replicate from (optional)
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--wait-start</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
wait for the standby to start (timeout in seconds, default 30 seconds)
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--wait-sync</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
wait for the node record to synchronise to the standby (optional timeout in seconds)
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
|
||||||
|
</variablelist>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1 id="repmgr-standby-register-events">
|
||||||
|
<title>Event notifications</title>
|
||||||
|
<para>
|
||||||
|
A <literal>standby_register</literal> <link linkend="event-notifications">event notification</link>
|
||||||
|
will be generated immediately after the node record is updated on the primary.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
If the <option>--wait-sync</option> option is provided, a <literal>standby_register_sync</literal>
|
||||||
|
event notification will be generated immediately after the node record has synchronised to the
|
||||||
|
standby.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
If provided, &repmgr; will substitute the placeholders <literal>%p</literal> with the node ID of the
|
||||||
|
primary node, <literal>%c</literal> with its <literal>conninfo</literal> string, and
|
||||||
|
<literal>%a</literal> with its node name.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
</refentry>
|
||||||
370
doc/repmgr-standby-switchover.sgml
Normal file
370
doc/repmgr-standby-switchover.sgml
Normal file
@@ -0,0 +1,370 @@
|
|||||||
|
<refentry id="repmgr-standby-switchover">
|
||||||
|
<indexterm>
|
||||||
|
<primary>repmgr standby switchover</primary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<refmeta>
|
||||||
|
<refentrytitle>repmgr standby switchover</refentrytitle>
|
||||||
|
</refmeta>
|
||||||
|
|
||||||
|
<refnamediv>
|
||||||
|
<refname>repmgr standby switchover</refname>
|
||||||
|
<refpurpose>promote a standby to primary and demote the existing primary to a standby</refpurpose>
|
||||||
|
</refnamediv>
|
||||||
|
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Description</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 nodes are connected to the demotion candidate, &repmgr; can instruct
|
||||||
|
these to follow the new primary if the option <literal>--siblings-follow</literal>
|
||||||
|
is specified. This requires a passwordless SSH connection between the promotion
|
||||||
|
candidate (new primary) and the nodes attached to the demotion candidate
|
||||||
|
(existing primary).
|
||||||
|
</para>
|
||||||
|
<note>
|
||||||
|
<para>
|
||||||
|
Performing a switchover is a non-trivial operation. In particular it
|
||||||
|
relies on the current primary being able to shut down cleanly and quickly.
|
||||||
|
&repmgr; will attempt to check for potential issues but cannot guarantee
|
||||||
|
a successful switchover.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
&repmgr; will refuse to perform the switchover if an exclusive backup is running on
|
||||||
|
the current primary, or if WAL replay is paused on the standby.
|
||||||
|
</para>
|
||||||
|
</note>
|
||||||
|
<para>
|
||||||
|
For more details on performing a switchover, including preparation and configuration,
|
||||||
|
see section <xref linkend="performing-switchover">.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<note>
|
||||||
|
<para>
|
||||||
|
From <link linkend="release-4.2">repmgr 4.2</link>, &repmgr; will instruct any running
|
||||||
|
<application>repmgrd</application> instances to pause operations while the switchover
|
||||||
|
is being carried out, to prevent <application>repmgrd</application> from
|
||||||
|
unintentionally promoting a node. For more details, see <xref linkend="repmgrd-pausing">.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Users of &repmgr; versions prior to 4.2 should ensure that <application>repmgrd</application>
|
||||||
|
is not running on any nodes while a switchover is being executed.
|
||||||
|
</para>
|
||||||
|
</note>
|
||||||
|
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Options</title>
|
||||||
|
<variablelist>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--always-promote</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Promote standby to primary, even if it is behind or has diverged
|
||||||
|
from the original primary. The original primary will be shut down in any case,
|
||||||
|
and will need to be manually reintegrated into the replication cluster.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--dry-run</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Check prerequisites but don't actually execute a switchover.
|
||||||
|
</para>
|
||||||
|
<important>
|
||||||
|
<para>
|
||||||
|
Success of <option>--dry-run</option> does not imply the switchover will
|
||||||
|
complete successfully, only that
|
||||||
|
the prerequisites for performing the operation are met.
|
||||||
|
</para>
|
||||||
|
</important>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>-F</option></term>
|
||||||
|
<term><option>--force</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Ignore warnings and continue anyway.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Specifically, if a problem is encountered when shutting down the current primary,
|
||||||
|
using <option>-F/--force</option> will cause &repmgr; to continue by promoting
|
||||||
|
the standby to be the new primary, and if <option>--siblings-follow</option> is
|
||||||
|
specified, attach any other standbys to the new primary.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--force-rewind[=/path/to/pg_rewind]</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Use <application>pg_rewind</application> to reintegrate the old primary if necessary
|
||||||
|
(and the prerequisites for using <application>pg_rewind</application> are met).
|
||||||
|
If using PostgreSQL 9.3 or 9.4, and the <application>pg_rewind</application>
|
||||||
|
binary is not installed in the PostgreSQL <filename>bin</filename> directory,
|
||||||
|
provide its full path. For more details see also <xref linkend="switchover-pg-rewind">.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>-R</option></term>
|
||||||
|
<term><option>--remote-user</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
System username for remote SSH operations (defaults to local system user).
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--repmgrd-no-pause</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Don't pause <application>repmgrd</application> while executing a switchover.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
This option should not be used unless you take steps by other means
|
||||||
|
to ensure <application>repmgrd</application> is paused or not
|
||||||
|
running on all nodes.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
|
||||||
|
<term><option>--siblings-follow</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Have nodes attached to the old primary follow the new primary.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
This will also ensure that a witness node, if in use, is updated
|
||||||
|
with the new primary's data.
|
||||||
|
</para>
|
||||||
|
<note>
|
||||||
|
<para>
|
||||||
|
In a future &repmgr; release, <option>--siblings-follow</option> will be applied
|
||||||
|
by default.
|
||||||
|
</para>
|
||||||
|
</note>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Configuration file settings</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
The following parameters in <filename>repmgr.conf</filename> are relevant to the
|
||||||
|
switchover operation:
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<variablelist>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<indexterm>
|
||||||
|
<primary>replication_lag_critical</primary>
|
||||||
|
<secondary>with "repmgr standby switchover"</secondary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<term><option>replication_lag_critical</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
If replication lag (in seconds) on the standby exceeds this value, the
|
||||||
|
switchover will be aborted (unless the <literal>-F/--force</literal> option
|
||||||
|
is provided)
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<indexterm>
|
||||||
|
<primary>shutdown_check_timeout</primary>
|
||||||
|
<secondary>with "repmgr standby switchover"</secondary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<term><option>shutdown_check_timeout</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
The maximum number of seconds to wait for the
|
||||||
|
demotion candidate (current primary) to shut down, before aborting the switchover.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Note that this parameter is set on the node where <command>repmgr standby switchover</command>
|
||||||
|
is executed (promotion candidate); setting it on the demotion candidate (former primary) will
|
||||||
|
have no effect.
|
||||||
|
</para>
|
||||||
|
<note>
|
||||||
|
<para>
|
||||||
|
In versions prior to <link linkend="release-4.2">&repmgr; 4.2</link>, <command>repmgr standby switchover</command> would
|
||||||
|
use the values defined in <literal>reconnect_attempts</literal> and <literal>reconnect_interval</literal>
|
||||||
|
to determine the timeout for demotion candidate shutdown.
|
||||||
|
</para>
|
||||||
|
</note>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<indexterm>
|
||||||
|
<primary>wal_receive_check_timeout</primary>
|
||||||
|
<secondary>with "repmgr standby switchover"</secondary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<term><option>wal_receive_check_timeout</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
After the primary has shut down, the maximum number of seconds to wait for the
|
||||||
|
walreceiver on the standby to flush WAL to disk before comparing WAL receive location
|
||||||
|
with the primary's shut down location.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<indexterm>
|
||||||
|
<primary>standby_reconnect_timeout</primary>
|
||||||
|
<secondary>with "repmgr standby switchover"</secondary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<term><option>standby_reconnect_timeout</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
The maximum number of seconds to attempt to wait for the demotion candidate (former primary)
|
||||||
|
to reconnect to the promoted primary (default: 60 seconds)
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Note that this parameter is set on the node where <command>repmgr standby switchover</command>
|
||||||
|
is executed (promotion candidate); setting it on the demotion candidate (former primary) will
|
||||||
|
have no effect.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<indexterm>
|
||||||
|
<primary>node_rejoin_timeout</primary>
|
||||||
|
<secondary>with "repmgr standby switchover"</secondary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<term><option>node_rejoin_timeout</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
maximum number of seconds to attempt to wait for the demotion candidate (former primary)
|
||||||
|
to reconnect to the promoted primary (default: 60 seconds)
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Note that this parameter is set on the the demotion candidate (former primary);
|
||||||
|
setting it on the node where <command>repmgr standby switchover</command> is
|
||||||
|
executed will have no effect.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
However, this value <emphasis>must</emphasis> be less than <option>standby_reconnect_timeout</option> on the
|
||||||
|
promotion candidate (the node where <command>repmgr standby switchover</command> is executed).
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
</variablelist>
|
||||||
|
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Execution</title>
|
||||||
|
|
||||||
|
<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>
|
||||||
|
External database connections, e.g. from an application, should not be permitted while
|
||||||
|
the switchover is taking place. In particular, active transactions on the primary
|
||||||
|
can potentially disrupt the shutdown process.
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1 id="repmgr-standby-switchover-events">
|
||||||
|
<title>Event notifications</title>
|
||||||
|
<para>
|
||||||
|
<literal>standby_switchover</literal> and <literal>standby_promote</literal>
|
||||||
|
<link linkend="event-notifications">event notifications</link> will be generated for the new primary,
|
||||||
|
and a <literal>node_rejoin</literal> event notification for the former primary (new standby).
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
If using an event notification script, <literal>standby_switchover</literal>
|
||||||
|
will populate the placeholder parameter <literal>%p</literal> with the node ID of
|
||||||
|
the former primary.
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Exit codes</title>
|
||||||
|
<para>
|
||||||
|
One of the following exit codes will be emitted by <command>repmgr standby switchover</command>:
|
||||||
|
</para>
|
||||||
|
<variablelist>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>SUCCESS (0)</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
The switchover completed successfully; or if <option>--dry-run</option> was provided,
|
||||||
|
no issues were detected which would prevent the switchover operation.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>ERR_SWITCHOVER_FAIL (18)</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
The switchover could not be executed.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>ERR_SWITCHOVER_INCOMPLETE (22)</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
The switchover was executed but a problem was encountered.
|
||||||
|
Typically this means the former primary could not be reattached
|
||||||
|
as a standby. Check preceding log messages for more information.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
</variablelist>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>See also</title>
|
||||||
|
<para>
|
||||||
|
<xref linkend="repmgr-standby-follow">, <xref linkend="repmgr-node-rejoin">
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
For more details on performing a switchover operation, see the section <xref linkend="performing-switchover">.
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
</refentry>
|
||||||
70
doc/repmgr-standby-unregister.sgml
Normal file
70
doc/repmgr-standby-unregister.sgml
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
<refentry id="repmgr-standby-unregister">
|
||||||
|
<indexterm>
|
||||||
|
<primary>repmgr standby unregister</primary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<refmeta>
|
||||||
|
<refentrytitle>repmgr standby unregister</refentrytitle>
|
||||||
|
</refmeta>
|
||||||
|
|
||||||
|
<refnamediv>
|
||||||
|
<refname>repmgr standby unregister</refname>
|
||||||
|
<refpurpose>remove a standby's information from the &repmgr; metadata</refpurpose>
|
||||||
|
</refnamediv>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Description</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>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Execution</title>
|
||||||
|
<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 primary server will unregister the standby with
|
||||||
|
id <literal>3</literal>:
|
||||||
|
<programlisting>
|
||||||
|
repmgr standby unregister -f /etc/repmgr.conf --node-id=3</programlisting>
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Options</title>
|
||||||
|
<variablelist>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--node-id</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<varname>node_id</varname> of the node to unregister (optional)
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
</variablelist>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1 id="repmgr-standby-unregister-events">
|
||||||
|
<title>Event notifications</title>
|
||||||
|
<para>
|
||||||
|
A <literal>standby_unregister</literal> <link linkend="event-notifications">event notification</link> will be generated.
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
</refentry>
|
||||||
|
|
||||||
73
doc/repmgr-witness-register.sgml
Normal file
73
doc/repmgr-witness-register.sgml
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
<refentry id="repmgr-witness-register">
|
||||||
|
<indexterm>
|
||||||
|
<primary>repmgr witness register</primary>
|
||||||
|
<seealso>witness server</seealso>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<refmeta>
|
||||||
|
<refentrytitle>repmgr witness register</refentrytitle>
|
||||||
|
</refmeta>
|
||||||
|
|
||||||
|
<refnamediv>
|
||||||
|
<refname>repmgr witness register</refname>
|
||||||
|
<refpurpose>add a witness node's information to the &repmgr; metadata</refpurpose>
|
||||||
|
</refnamediv>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Description</title>
|
||||||
|
<para>
|
||||||
|
<command>repmgr witness register</command> adds a witness server's node
|
||||||
|
record to the &repmgr; metadata, and if necessary initialises the witness
|
||||||
|
node by installing the &repmgr; extension and copying the &repmgr; metadata
|
||||||
|
to the witness server. This command needs to be executed to enable
|
||||||
|
use of the witness server with <application>repmgrd</application>.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
When executing <command>repmgr witness register</command>, database connection
|
||||||
|
information for the cluster primary server must also be provided.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
In most cases it's only necessary to provide the primary's hostname with
|
||||||
|
the <option>-h</option>/<option>--host</option> option; &repmgr; will
|
||||||
|
automatically use the <varname>user</varname> and <varname>dbname</varname>
|
||||||
|
values defined in the <varname>conninfo</varname> string defined in the
|
||||||
|
witness node's <filename>repmgr.conf</filename>, unless these are explicitly
|
||||||
|
provided as command line options.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<note>
|
||||||
|
<para>
|
||||||
|
The primary server must be registered with <command><link linkend="repmgr-primary-register">repmgr primary register</link></command> before the witness
|
||||||
|
server can be registered.
|
||||||
|
</para>
|
||||||
|
</note>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Execute with the <option>--dry-run</option> option to check what would happen
|
||||||
|
without actually registering the witness server.
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
<refsect1>
|
||||||
|
<title>Example</title>
|
||||||
|
<para>
|
||||||
|
<programlisting>
|
||||||
|
$ repmgr -f /etc/repmgr.conf witness register -h node1
|
||||||
|
INFO: connecting to witness node "node3" (ID: 3)
|
||||||
|
INFO: connecting to primary node
|
||||||
|
NOTICE: attempting to install extension "repmgr"
|
||||||
|
NOTICE: "repmgr" extension successfully installed
|
||||||
|
INFO: witness registration complete
|
||||||
|
NOTICE: witness node "node3" (ID: 3) successfully registered
|
||||||
|
</programlisting>
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
|
||||||
|
<refsect1 id="repmgr-witness-register-events">
|
||||||
|
<title>Event notifications</title>
|
||||||
|
<para>
|
||||||
|
A <literal>witness_register</literal> <link linkend="event-notifications">event notification</link> will be generated.
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
</refentry>
|
||||||
102
doc/repmgr-witness-unregister.sgml
Normal file
102
doc/repmgr-witness-unregister.sgml
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
<refentry id="repmgr-witness-unregister" xreflabel="repmgr witness unregister">
|
||||||
|
<indexterm>
|
||||||
|
<primary>repmgr witness unregister</primary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<refmeta>
|
||||||
|
<refentrytitle>repmgr witness unregister</refentrytitle>
|
||||||
|
</refmeta>
|
||||||
|
|
||||||
|
<refnamediv>
|
||||||
|
<refname>repmgr witness unregister</refname>
|
||||||
|
<refpurpose>remove a witness node's information to the &repmgr; metadata</refpurpose>
|
||||||
|
</refnamediv>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Description</title>
|
||||||
|
<para>
|
||||||
|
<command>repmgr witness unregister</command> removes a witness server's node
|
||||||
|
record from the &repmgr; metadata.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The node does not have to be running to be unregistered, however if this is the
|
||||||
|
case then either provide connection information for the primary server, or
|
||||||
|
execute <command>repmgr witness unregister</command> on a running node and
|
||||||
|
provide the parameter <option>--node-id</option> with the node ID of the
|
||||||
|
witness server.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Execute with the <literal>--dry-run</literal> option to check what would happen
|
||||||
|
without actually registering the witness server.
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
<refsect1>
|
||||||
|
<title>Examples</title>
|
||||||
|
<para>
|
||||||
|
Unregistering a running witness node:
|
||||||
|
<programlisting>
|
||||||
|
$ repmgr -f /etc/repmgr.conf witness unregister
|
||||||
|
INFO: connecting to witness node "node3" (ID: 3)
|
||||||
|
INFO: unregistering witness node 3
|
||||||
|
INFO: witness unregistration complete
|
||||||
|
DETAIL: witness node with UD 3 successfully unregistered</programlisting>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Unregistering a non-running witness node:
|
||||||
|
<programlisting>
|
||||||
|
$ repmgr -f /etc/repmgr.conf witness unregister -h node1 -p 5501 -F
|
||||||
|
INFO: connecting to node "node3" (ID: 3)
|
||||||
|
NOTICE: unable to connect to node "node3" (ID: 3), removing node record on cluster primary only
|
||||||
|
INFO: unregistering witness node 3
|
||||||
|
INFO: witness unregistration complete
|
||||||
|
DETAIL: witness node with id ID 3 successfully unregistered</programlisting>
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Notes</title>
|
||||||
|
<para>
|
||||||
|
This command will not make any changes to the witness node itself and will neither
|
||||||
|
remove any data from the witness database nor stop the PostgreSQL instance.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
A witness node which has been unregistered, can be re-registered with
|
||||||
|
<link linkend="repmgr-witness-register">repmgr witness register --force</link>.
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
|
||||||
|
<title>Options</title>
|
||||||
|
<variablelist>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--dry-run</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Check prerequisites but don't actually unregister the witness.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--node-id</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Unregister witness server with the specified node ID.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
</variablelist>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
|
||||||
|
<refsect1 id="repmgr-witness-unregister-events">
|
||||||
|
<title>Event notifications</title>
|
||||||
|
<para>
|
||||||
|
A <literal>witness_unregister</literal> <link linkend="event-notifications">event notification</link> will be generated.
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
</refentry>
|
||||||
134
doc/repmgr.sgml
Normal file
134
doc/repmgr.sgml
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
<!-- 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 repmgrd "<productname>repmgrd</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>
|
||||||
|
This is the official documentation of &repmgr; &repmgrversion; for
|
||||||
|
use with PostgreSQL 9.3 - PostgreSQL 11.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
&repmgr; is being continually developed and we strongly recommend using the
|
||||||
|
latest version. Please check the
|
||||||
|
<ulink url="https://repmgr.org/">repmgr website</ulink> for details
|
||||||
|
about the current &repmgr; version as well as the
|
||||||
|
<ulink url="https://repmgr.org/docs/current/index.html">current repmgr documentation</ulink>.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
&repmgr; is 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</ulink>
|
||||||
|
or <ulink url="https://groups.google.com/group/repmgr">the mailing list/forum</ulink>.
|
||||||
|
Multiple 2ndQuadrant customers contribute funding
|
||||||
|
to make repmgr development possible.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
&repmgr; is fully supported by 2ndQuadrant's
|
||||||
|
<ulink url="https://www.2ndquadrant.com/en/support/support-postgresql/">24/7 Production Support</ulink>.
|
||||||
|
2ndQuadrant, a Major Sponsor of the PostgreSQL project, continues to develop and maintain &repmgr;.
|
||||||
|
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-overview;
|
||||||
|
&repmgrd-automatic-failover;
|
||||||
|
&repmgrd-configuration;
|
||||||
|
&repmgrd-operation;
|
||||||
|
&repmgrd-bdr;
|
||||||
|
</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-witness-register;
|
||||||
|
&repmgr-witness-unregister;
|
||||||
|
&repmgr-node-status;
|
||||||
|
&repmgr-node-check;
|
||||||
|
&repmgr-node-rejoin;
|
||||||
|
&repmgr-node-service;
|
||||||
|
&repmgr-cluster-show;
|
||||||
|
&repmgr-cluster-matrix;
|
||||||
|
&repmgr-cluster-crosscheck;
|
||||||
|
&repmgr-cluster-event;
|
||||||
|
&repmgr-cluster-cleanup;
|
||||||
|
&repmgr-daemon-status;
|
||||||
|
&repmgr-daemon-start;
|
||||||
|
&repmgr-daemon-stop;
|
||||||
|
&repmgr-daemon-pause;
|
||||||
|
&repmgr-daemon-unpause;
|
||||||
|
</part>
|
||||||
|
|
||||||
|
&appendix-release-notes;
|
||||||
|
&appendix-signatures;
|
||||||
|
&appendix-faq;
|
||||||
|
&appendix-packages;
|
||||||
|
&appendix-support;
|
||||||
|
|
||||||
|
<![%include-index;[&bookindex;]]>
|
||||||
|
<![%include-xslt-index;[<index id="bookindex"></index>]]>
|
||||||
|
|
||||||
|
</book>
|
||||||
297
doc/repmgrd-automatic-failover.sgml
Normal file
297
doc/repmgrd-automatic-failover.sgml
Normal file
@@ -0,0 +1,297 @@
|
|||||||
|
<chapter id="repmgrd-automatic-failover" xreflabel="Automatic failover with repmgrd">
|
||||||
|
<indexterm>
|
||||||
|
<primary>repmgrd</primary>
|
||||||
|
<secondary>automatic failover</secondary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<title>Automatic failover with repmgrd</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
<application>repmgrd</application> 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>
|
||||||
|
|
||||||
|
<sect1 id="repmgrd-witness-server" xreflabel="Using a witness server with repmgrd">
|
||||||
|
<indexterm>
|
||||||
|
<primary>repmgrd</primary>
|
||||||
|
<secondary>witness server</secondary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<indexterm>
|
||||||
|
<primary>witness server</primary>
|
||||||
|
<secondary>repmgrd</secondary>
|
||||||
|
</indexterm>
|
||||||
|
<title>Using a witness server</title>
|
||||||
|
<para>
|
||||||
|
A <xref linkend="witness-server"> is a normal PostgreSQL instance which
|
||||||
|
is not part of the streaming replication cluster; its purpose is, if a
|
||||||
|
failover situation occurs, to provide proof that it is the primary server
|
||||||
|
itself which is unavailable, rather than e.g. a network split between
|
||||||
|
different physical locations.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
A typical use case for a witness server is a two-node streaming replication
|
||||||
|
setup, where the primary and standby are in different locations (data centres).
|
||||||
|
By creating a witness server in the same location (data centre) as the primary,
|
||||||
|
if the primary becomes unavailable it's possible for the standby to decide whether
|
||||||
|
it can promote itself without risking a "split brain" scenario: if it can't see either the
|
||||||
|
witness or the primary server, it's likely there's a network-level interruption
|
||||||
|
and it should not promote itself. If it can see the witness but not the primary,
|
||||||
|
this proves there is no network interruption and the primary itself is unavailable,
|
||||||
|
and it can therefore promote itself (and ideally take action to fence the
|
||||||
|
former primary).
|
||||||
|
</para>
|
||||||
|
<note>
|
||||||
|
<para>
|
||||||
|
<emphasis>Never</emphasis> install a witness server on the same physical host
|
||||||
|
as another node in the replication cluster managed by &repmgr; - it's essential
|
||||||
|
the witness is not affected in any way by failure of another node.
|
||||||
|
</para>
|
||||||
|
</note>
|
||||||
|
<para>
|
||||||
|
For more complex replication scenarios,e.g. with multiple datacentres, it may
|
||||||
|
be preferable to use location-based failover, which ensures that only nodes
|
||||||
|
in the same location as the primary will ever be promotion candidates;
|
||||||
|
see <xref linkend="repmgrd-network-split"> for more details.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<note>
|
||||||
|
<simpara>
|
||||||
|
A witness server will only be useful if <application>repmgrd</application>
|
||||||
|
is in use.
|
||||||
|
</simpara>
|
||||||
|
</note>
|
||||||
|
|
||||||
|
<sect2 id="creating-witness-server">
|
||||||
|
<title>Creating a witness server</title>
|
||||||
|
<para>
|
||||||
|
To create a witness server, set up a normal PostgreSQL instance on a server
|
||||||
|
in the same physical location as the cluster's primary server.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
This instance should <emphasis>not</emphasis> be on the same physical host as the primary server,
|
||||||
|
as otherwise if the primary server fails due to hardware issues, the witness
|
||||||
|
server will be lost too.
|
||||||
|
</para>
|
||||||
|
<note>
|
||||||
|
<simpara>
|
||||||
|
&repmgr; 3.3 and earlier provided a <command>repmgr create witness</command>
|
||||||
|
command, which would automatically create a PostgreSQL instance. However
|
||||||
|
this often resulted in an unsatisfactory, hard-to-customise instance.
|
||||||
|
</simpara>
|
||||||
|
</note>
|
||||||
|
<para>
|
||||||
|
The witness server should be configured in the same way as a normal
|
||||||
|
&repmgr; node; see section <xref linkend="configuration">.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Register the witness server with <xref linkend="repmgr-witness-register">.
|
||||||
|
This will create the &repmgr; extension on the witness server, and make
|
||||||
|
a copy of the &repmgr; metadata.
|
||||||
|
</para>
|
||||||
|
<note>
|
||||||
|
<simpara>
|
||||||
|
As the witness server is not part of the replication cluster, further
|
||||||
|
changes to the &repmgr; metadata will be synchronised by
|
||||||
|
<application>repmgrd</application>.
|
||||||
|
</simpara>
|
||||||
|
</note>
|
||||||
|
<para>
|
||||||
|
Once the witness server has been configured, <application>repmgrd</application>
|
||||||
|
should be started.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
To unregister a witness server, use <xref linkend="repmgr-witness-unregister">.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
</sect1>
|
||||||
|
|
||||||
|
|
||||||
|
<sect1 id="repmgrd-network-split" xreflabel="Handling network splits with repmgrd">
|
||||||
|
<indexterm>
|
||||||
|
<primary>repmgrd</primary>
|
||||||
|
<secondary>network splits</secondary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<indexterm>
|
||||||
|
<primary>network splits</primary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<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>
|
||||||
|
&repmgr; enables provision of "<xref linkend="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, <application>repmgrd</application> will check if any servers in the
|
||||||
|
same location as the current primary node are visible. If not, <application>repmgrd</application>
|
||||||
|
will assume a network interruption and not promote any node in any
|
||||||
|
other location (it will however enter <link linkend="repmgrd-degraded-monitoring">degraded monitoring</link>
|
||||||
|
mode until a primary becomes visible).
|
||||||
|
</para>
|
||||||
|
|
||||||
|
</sect1>
|
||||||
|
|
||||||
|
<sect1 id="repmgrd-standby-disconnection-on-failover" xreflabel="Standby disconnection on failover">
|
||||||
|
<indexterm>
|
||||||
|
<primary>repmgrd</primary>
|
||||||
|
<secondary>standby disconnection on failover</secondary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<indexterm>
|
||||||
|
<primary>standby disconnection on failover</primary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<title>Standby disconnection on failover</title>
|
||||||
|
<para>
|
||||||
|
If <option>standby_disconnect_on_failover</option> is set to <literal>true</literal> in
|
||||||
|
<filename>repmgr.conf</filename>, in a failover situation <application>repmgrd</application> will forcibly disconnect
|
||||||
|
the local node's WAL receiver before making a failover decision.
|
||||||
|
</para>
|
||||||
|
<note>
|
||||||
|
<para>
|
||||||
|
<option>standby_disconnect_on_failover</option> is available from PostgreSQL 9.5 and later.
|
||||||
|
Additionally this requires that the <literal>repmgr</literal> database user is a superuser.
|
||||||
|
</para>
|
||||||
|
</note>
|
||||||
|
<para>
|
||||||
|
By doing this, it's possible to ensure that, at the point the failover decision is made, no nodes
|
||||||
|
are receiving data from the primary and their LSN location will be static.
|
||||||
|
</para>
|
||||||
|
<important>
|
||||||
|
<para>
|
||||||
|
<option>standby_disconnect_on_failover</option> <emphasis>must</emphasis> be set to the same value on
|
||||||
|
all nodes.
|
||||||
|
</para>
|
||||||
|
</important>
|
||||||
|
<para>
|
||||||
|
Note that when using <option>standby_disconnect_on_failover</option> there will be a delay of 5 seconds
|
||||||
|
plus however many seconds it takes to confirm the WAL receiver is disconnected before
|
||||||
|
<application>repmgrd</application> proceeds with the failover decision.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Following the failover operation, no matter what the outcome, each node will reconnect its WAL receiver.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
</sect1>
|
||||||
|
|
||||||
|
<sect1 id="repmgrd-failover-validation" xreflabel="Failover validation">
|
||||||
|
<indexterm>
|
||||||
|
<primary>repmgrd</primary>
|
||||||
|
<secondary>failover validation</secondary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<indexterm>
|
||||||
|
<primary>failover validation</primary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<title>Failover validation</title>
|
||||||
|
<para>
|
||||||
|
From <link linkend="release-4.3">repmgr 4.3</link>, &repmgr; makes it possible to provide a script
|
||||||
|
to <application>repmgrd</application> which, in a failover situation,
|
||||||
|
will be executed by the promotion candidate (the node which has been selected
|
||||||
|
to be the new primary) to confirm whether the node should actually be promoted.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
To use this, <option>failover_validation_command</option> in <filename>repmgr.conf</filename>
|
||||||
|
to a script executable by the <literal>postgres</literal> system user, e.g.:
|
||||||
|
<programlisting>
|
||||||
|
failover_validation_command=/path/to/script.sh %n %a</programlisting>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The <literal>%n</literal> parameter will be replaced with the node ID, and the
|
||||||
|
<literal>%a</literal> parameter will be replaced by the node name when the script is executed.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
This script must return an exit code of <literal>0</literal> to indicate the node should promote itself.
|
||||||
|
Any other value will result in the promotion being aborted and the election rerun.
|
||||||
|
There is a pause of <option>election_rerun_interval</option> seconds before the election is rerun.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Sample <application>repmgrd</application> log file output during which the failover validation
|
||||||
|
script rejects the proposed promotion candidate:
|
||||||
|
<programlisting>
|
||||||
|
[2019-03-13 21:01:30] [INFO] visible nodes: 2; total nodes: 2; no nodes have seen the primary within the last 4 seconds
|
||||||
|
[2019-03-13 21:01:30] [NOTICE] promotion candidate is "node2" (ID: 2)
|
||||||
|
[2019-03-13 21:01:30] [NOTICE] executing "failover_validation_command"
|
||||||
|
[2019-03-13 21:01:30] [DETAIL] /usr/local/bin/failover-validation.sh 2
|
||||||
|
[2019-03-13 21:01:30] [INFO] output returned by failover validation command:
|
||||||
|
Node ID: 2
|
||||||
|
|
||||||
|
[2019-03-13 21:01:30] [NOTICE] failover validation command returned a non-zero value: "1"
|
||||||
|
[2019-03-13 21:01:30] [NOTICE] promotion candidate election will be rerun
|
||||||
|
[2019-03-13 21:01:30] [INFO] 1 followers to notify
|
||||||
|
[2019-03-13 21:01:30] [NOTICE] notifying node "node3" (node ID: 3) to rerun promotion candidate selection
|
||||||
|
INFO: node 3 received notification to rerun promotion candidate election
|
||||||
|
[2019-03-13 21:01:30] [NOTICE] rerunning election after 15 seconds ("election_rerun_interval")</programlisting>
|
||||||
|
</para>
|
||||||
|
|
||||||
|
|
||||||
|
</sect1>
|
||||||
|
|
||||||
|
<sect1 id="cascading-replication" xreflabel="Cascading replication">
|
||||||
|
<indexterm>
|
||||||
|
<primary>repmgrd</primary>
|
||||||
|
<secondary>cascading replication</secondary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<indexterm>
|
||||||
|
<primary>cascading replication</primary>
|
||||||
|
<secondary>repmgrd</secondary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<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
|
||||||
|
<application>repmgrd</application> 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
|
||||||
|
(unless <varname>failover</varname> is set to <literal>manual</literal> in
|
||||||
|
<filename>repmgr.conf</filename>).
|
||||||
|
</para>
|
||||||
|
|
||||||
|
</sect1>
|
||||||
|
|
||||||
|
|
||||||
|
</chapter>
|
||||||
428
doc/repmgrd-bdr.sgml
Normal file
428
doc/repmgrd-bdr.sgml
Normal file
@@ -0,0 +1,428 @@
|
|||||||
|
<chapter id="repmgrd-bdr">
|
||||||
|
<indexterm>
|
||||||
|
<primary>repmgrd</primary>
|
||||||
|
<secondary>BDR</secondary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<indexterm>
|
||||||
|
<primary>BDR</primary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<title>BDR failover with repmgrd</title>
|
||||||
|
<para>
|
||||||
|
&repmgr; 4.x provides support for monitoring a pair of BDR 2.x nodes and taking action in
|
||||||
|
case one of the nodes fails.
|
||||||
|
</para>
|
||||||
|
<note>
|
||||||
|
<simpara>
|
||||||
|
Due to the nature of BDR 1.x/2.x, it's only safe to use this solution for
|
||||||
|
a two-node scenario. Introducing additional nodes will create an inherent
|
||||||
|
risk of node desynchronisation if a node goes down without being cleanly
|
||||||
|
removed from the cluster.
|
||||||
|
</simpara>
|
||||||
|
</note>
|
||||||
|
<para>
|
||||||
|
In contrast to streaming replication, there's no concept of "promoting" a new
|
||||||
|
primary node with BDR. Instead, "failover" involves monitoring both nodes
|
||||||
|
with <application>repmgrd</application> and redirecting queries from the failed node to the remaining
|
||||||
|
active node. This can be done by using an
|
||||||
|
<link linkend="event-notifications">event notification</link> script
|
||||||
|
which is called by <application>repmgrd</application> to dynamically
|
||||||
|
reconfigure a proxy server/connection pooler such as <application>PgBouncer</application>.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<note>
|
||||||
|
<simpara>
|
||||||
|
This &repmgr; functionality is for BDR 2.x only running on PostgreSQL 9.4/9.6.
|
||||||
|
It is <emphasis>not</emphasis> required for later BDR versions.
|
||||||
|
</simpara>
|
||||||
|
</note>
|
||||||
|
|
||||||
|
<sect1 id="bdr-prerequisites" xreflabel="BDR prequisites">
|
||||||
|
<title>Prerequisites</title>
|
||||||
|
<important>
|
||||||
|
<para>
|
||||||
|
This &repmgr; functionality is for BDR 2.x only running on PostgreSQL 9.4/9.6.
|
||||||
|
It is <emphasis>not</emphasis> required for later BDR versions.
|
||||||
|
</para>
|
||||||
|
</important>
|
||||||
|
<para>
|
||||||
|
&repmgr; 4 requires PostgreSQL 9.4 or 9.6 with the BDR 2 extension
|
||||||
|
enabled and configured for a two-node BDR network. &repmgr; 4 packages
|
||||||
|
must be installed on each node before attempting to configure
|
||||||
|
<application>repmgr</application>.
|
||||||
|
</para>
|
||||||
|
<note>
|
||||||
|
<simpara>
|
||||||
|
&repmgr; 4 will refuse to install if it detects more than two BDR nodes.
|
||||||
|
</simpara>
|
||||||
|
</note>
|
||||||
|
<para>
|
||||||
|
Application database connections *must* be passed through a proxy server/
|
||||||
|
connection pooler such as <application>PgBouncer</application>, and it must be possible to dynamically
|
||||||
|
reconfigure that from <application>repmgrd</application>. The example demonstrated in this document
|
||||||
|
will use <application>PgBouncer</application>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The proxy server / connection poolers must <emphasis>not</emphasis>
|
||||||
|
be installed on the database servers.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
For this example, it's assumed password-less SSH connections are available
|
||||||
|
from the PostgreSQL servers to the servers where <application>PgBouncer</application>
|
||||||
|
runs, and that the user on those servers has permission to alter the
|
||||||
|
<application>PgBouncer</application> configuration files.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
PostgreSQL connections must be possible between each node, and each node
|
||||||
|
must be able to connect to each PgBouncer instance.
|
||||||
|
</para>
|
||||||
|
</sect1>
|
||||||
|
|
||||||
|
<sect1 id="bdr-configuration" xreflabel="BDR configuration">
|
||||||
|
<title>Configuration</title>
|
||||||
|
<para>
|
||||||
|
A sample configuration for <filename>repmgr.conf</filename> on each
|
||||||
|
BDR node would look like this:
|
||||||
|
<programlisting>
|
||||||
|
# Node information
|
||||||
|
node_id=1
|
||||||
|
node_name='node1'
|
||||||
|
conninfo='host=node1 dbname=bdrtest user=repmgr connect_timeout=2'
|
||||||
|
data_directory='/var/lib/postgresql/data'
|
||||||
|
replication_type='bdr'
|
||||||
|
|
||||||
|
# Event notification configuration
|
||||||
|
event_notifications=bdr_failover
|
||||||
|
event_notification_command='/path/to/bdr-pgbouncer.sh %n %e %s "%c" "%a" >> /tmp/bdr-failover.log 2>&1'
|
||||||
|
|
||||||
|
# repmgrd options
|
||||||
|
monitor_interval_secs=5
|
||||||
|
reconnect_attempts=6
|
||||||
|
reconnect_interval=5</programlisting>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Adjust settings as appropriate; copy and adjust for the second node (particularly
|
||||||
|
the values <varname>node_id</varname>, <varname>node_name</varname>
|
||||||
|
and <varname>conninfo</varname>).
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Note that the values provided for the <varname>conninfo</varname> string
|
||||||
|
must be valid for connections from <emphasis>both</emphasis> nodes in the
|
||||||
|
replication cluster. The database must be the BDR-enabled database.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
If defined, the <varname>event_notifications</varname> parameter will restrict
|
||||||
|
execution of the script defined in <varname>event_notification_command</varname>
|
||||||
|
to the specified event(s).
|
||||||
|
</para>
|
||||||
|
<note>
|
||||||
|
<simpara>
|
||||||
|
<varname>event_notification_command</varname> is the script which does the actual "heavy lifting"
|
||||||
|
of reconfiguring the proxy server/ connection pooler. It is fully
|
||||||
|
user-definable; see section <xref linkend="bdr-event-notification-command"> for a reference
|
||||||
|
implementation.
|
||||||
|
</simpara>
|
||||||
|
</note>
|
||||||
|
|
||||||
|
</sect1>
|
||||||
|
|
||||||
|
<sect1 id="bdr-repmgr-setup" xreflabel="repmgr setup with BDR">
|
||||||
|
<title>repmgr setup</title>
|
||||||
|
<para>
|
||||||
|
Register both nodes; example on <literal>node1</literal>:
|
||||||
|
<programlisting>
|
||||||
|
$ repmgr -f /etc/repmgr.conf bdr register
|
||||||
|
NOTICE: attempting to install extension "repmgr"
|
||||||
|
NOTICE: "repmgr" extension successfully installed
|
||||||
|
NOTICE: node record created for node 'node1' (ID: 1)
|
||||||
|
NOTICE: BDR node 1 registered (conninfo: host=node1 dbname=bdrtest user=repmgr)</programlisting>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
and on <literal>node1</literal>:
|
||||||
|
<programlisting>
|
||||||
|
$ repmgr -f /etc/repmgr.conf bdr register
|
||||||
|
NOTICE: node record created for node 'node2' (ID: 2)
|
||||||
|
NOTICE: BDR node 2 registered (conninfo: host=node2 dbname=bdrtest user=repmgr)</programlisting>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The <literal>repmgr</literal> extension will be automatically created
|
||||||
|
when the first node is registered, and will be propagated to the second
|
||||||
|
node.
|
||||||
|
</para>
|
||||||
|
<important>
|
||||||
|
<simpara>
|
||||||
|
Ensure the &repmgr; package is available on both nodes before
|
||||||
|
attempting to register the first node.
|
||||||
|
</simpara>
|
||||||
|
</important>
|
||||||
|
<para>
|
||||||
|
At this point the meta data for both nodes has been created; executing
|
||||||
|
<xref linkend="repmgr-cluster-show"> (on either node) should produce output like this:
|
||||||
|
<programlisting>
|
||||||
|
$ repmgr -f /etc/repmgr.conf cluster show
|
||||||
|
ID | Name | Role | Status | Upstream | Location | Connection string
|
||||||
|
----+-------+------+-----------+----------+--------------------------------------------------------
|
||||||
|
1 | node1 | bdr | * running | | default | host=node1 dbname=bdrtest user=repmgr connect_timeout=2
|
||||||
|
2 | node2 | bdr | * running | | default | host=node2 dbname=bdrtest user=repmgr connect_timeout=2</programlisting>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Additionally it's possible to display log of significant events; executing
|
||||||
|
<xref linkend="repmgr-cluster-event"> (on either node) should produce output like this:
|
||||||
|
<programlisting>
|
||||||
|
$ repmgr -f /etc/repmgr.conf cluster event
|
||||||
|
Node ID | Event | OK | Timestamp | Details
|
||||||
|
---------+--------------+----+---------------------+----------------------------------------------
|
||||||
|
2 | bdr_register | t | 2017-07-27 17:51:48 | node record created for node 'node2' (ID: 2)
|
||||||
|
1 | bdr_register | t | 2017-07-27 17:51:00 | node record created for node 'node1' (ID: 1)
|
||||||
|
</programlisting>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
At this point there will only be records for the two node registrations (displayed here
|
||||||
|
in reverse chronological order).
|
||||||
|
</para>
|
||||||
|
</sect1>
|
||||||
|
|
||||||
|
<sect1 id="bdr-event-notification-command" xreflabel="Defining the BDR failover "event_notification command"">
|
||||||
|
<title>Defining the BDR failover "event_notification_command"</title>
|
||||||
|
<para>
|
||||||
|
Key to "failover" execution is the <literal>event_notification_command</literal>,
|
||||||
|
which is a user-definable script specified in <filename>repmpgr.conf</filename>
|
||||||
|
and which can use a &repmgr; <link linkend="event-notifications">event notification</link>
|
||||||
|
to reconfigure the proxy server / connection pooler so it points to the other, still-active node.
|
||||||
|
Details of the event will be passed as parameters to the script.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Following parameter placeholders are available for the script definition in <filename>repmpgr.conf</filename>;
|
||||||
|
these will be replaced with the appropriate value when the script is executed:
|
||||||
|
</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>
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>%c</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
conninfo string of the next available node (<varname>bdr_failover</varname> and <varname>bdr_recovery</varname>)
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>%a</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
name of the next available node (<varname>bdr_failover</varname> and <varname>bdr_recovery</varname>)
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Note that <literal>%c</literal> and <literal>%a</literal> are only provided with
|
||||||
|
particular failover events, in this case <varname>bdr_failover</varname>.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The provided sample script
|
||||||
|
(<literal><ulink url="https://raw.githubusercontent.com/2ndQuadrant/repmgr/master/scripts/bdr-pgbouncer.sh">scripts/bdr-pgbouncer.sh</ulink></literal>)
|
||||||
|
is configured as follows:
|
||||||
|
<programlisting>
|
||||||
|
event_notification_command='/path/to/bdr-pgbouncer.sh %n %e %s "%c" "%a"'</programlisting>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
and parses the placeholder parameters like this:
|
||||||
|
<programlisting>
|
||||||
|
NODE_ID=$1
|
||||||
|
EVENT_TYPE=$2
|
||||||
|
SUCCESS=$3
|
||||||
|
NEXT_CONNINFO=$4
|
||||||
|
NEXT_NODE_NAME=$5</programlisting>
|
||||||
|
</para>
|
||||||
|
<note>
|
||||||
|
<para>
|
||||||
|
The sample script also contains some hard-coded values for the <application>PgBouncer</application>
|
||||||
|
configuration for both nodes; these will need to be adjusted for your local environment
|
||||||
|
(ideally the scripts would be maintained as templates and generated by some
|
||||||
|
kind of provisioning system).
|
||||||
|
</para>
|
||||||
|
</note>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
The script performs following steps:
|
||||||
|
<itemizedlist spacing="compact" mark="bullet">
|
||||||
|
<listitem>
|
||||||
|
<simpara>pauses <application>PgBouncer</application> on all nodes</simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara>recreates the <application>PgBouncer</application> configuration file on each
|
||||||
|
node using the information provided by <application>repmgrd</application>
|
||||||
|
(primarily the <varname>conninfo</varname> string) to configure
|
||||||
|
<application>PgBouncer</application></simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara>reloads the <application>PgBouncer</application> configuration</simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara>executes the <command>RESUME</command> command (in <application>PgBouncer</application>)</simpara>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Following successful script execution, any connections to PgBouncer on the failed BDR node
|
||||||
|
will be redirected to the active node.
|
||||||
|
</para>
|
||||||
|
</sect1>
|
||||||
|
|
||||||
|
<sect1 id="bdr-monitoring-failover" xreflabel="Node monitoring and failover">
|
||||||
|
<title>Node monitoring and failover</title>
|
||||||
|
<para>
|
||||||
|
At the intervals specified by <varname>monitor_interval_secs</varname>
|
||||||
|
in <filename>repmgr.conf</filename>, <application>repmgrd</application>
|
||||||
|
will ping each node to check if it's available. If a node isn't available,
|
||||||
|
<application>repmgrd</application> will enter failover mode and check <varname>reconnect_attempts</varname>
|
||||||
|
times at intervals of <varname>reconnect_interval</varname> to confirm the node is definitely unreachable.
|
||||||
|
This buffer period is necessary to avoid false positives caused by transient
|
||||||
|
network outages.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
If the node is still unavailable, <application>repmgrd</application> will enter failover mode and execute
|
||||||
|
the script defined in <varname>event_notification_command</varname>; an entry will be logged
|
||||||
|
in the <literal>repmgr.events</literal> table and <application>repmgrd</application> will
|
||||||
|
(unless otherwise configured) resume monitoring of the node in "degraded" mode until it reappears.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
<application>repmgrd</application> logfile output during a failover event will look something like this
|
||||||
|
on one node (usually the node which has failed, here <literal>node2</literal>):
|
||||||
|
<programlisting>
|
||||||
|
...
|
||||||
|
[2017-07-27 21:08:39] [INFO] starting continuous BDR node monitoring
|
||||||
|
[2017-07-27 21:08:39] [INFO] monitoring BDR replication status on node "node2" (ID: 2)
|
||||||
|
[2017-07-27 21:08:55] [INFO] monitoring BDR replication status on node "node2" (ID: 2)
|
||||||
|
[2017-07-27 21:09:11] [INFO] monitoring BDR replication status on node "node2" (ID: 2)
|
||||||
|
[2017-07-27 21:09:23] [WARNING] unable to connect to node node2 (ID 2)
|
||||||
|
[2017-07-27 21:09:23] [INFO] checking state of node 2, 0 of 5 attempts
|
||||||
|
[2017-07-27 21:09:23] [INFO] sleeping 1 seconds until next reconnection attempt
|
||||||
|
[2017-07-27 21:09:24] [INFO] checking state of node 2, 1 of 5 attempts
|
||||||
|
[2017-07-27 21:09:24] [INFO] sleeping 1 seconds until next reconnection attempt
|
||||||
|
[2017-07-27 21:09:25] [INFO] checking state of node 2, 2 of 5 attempts
|
||||||
|
[2017-07-27 21:09:25] [INFO] sleeping 1 seconds until next reconnection attempt
|
||||||
|
[2017-07-27 21:09:26] [INFO] checking state of node 2, 3 of 5 attempts
|
||||||
|
[2017-07-27 21:09:26] [INFO] sleeping 1 seconds until next reconnection attempt
|
||||||
|
[2017-07-27 21:09:27] [INFO] checking state of node 2, 4 of 5 attempts
|
||||||
|
[2017-07-27 21:09:27] [INFO] sleeping 1 seconds until next reconnection attempt
|
||||||
|
[2017-07-27 21:09:28] [WARNING] unable to reconnect to node 2 after 5 attempts
|
||||||
|
[2017-07-27 21:09:28] [NOTICE] setting node record for node 2 to inactive
|
||||||
|
[2017-07-27 21:09:28] [INFO] executing notification command for event "bdr_failover"
|
||||||
|
[2017-07-27 21:09:28] [DETAIL] command is:
|
||||||
|
/path/to/bdr-pgbouncer.sh 2 bdr_failover 1 "host=host=node1 dbname=bdrtest user=repmgr connect_timeout=2" "node1"
|
||||||
|
[2017-07-27 21:09:28] [INFO] node 'node2' (ID: 2) detected as failed; next available node is 'node1' (ID: 1)
|
||||||
|
[2017-07-27 21:09:28] [INFO] monitoring BDR replication status on node "node2" (ID: 2)
|
||||||
|
[2017-07-27 21:09:28] [DETAIL] monitoring node "node2" (ID: 2) in degraded mode
|
||||||
|
...</programlisting>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Output on the other node (<literal>node1</literal>) during the same event will look like this:
|
||||||
|
<programlisting>
|
||||||
|
...
|
||||||
|
[2017-07-27 21:08:35] [INFO] starting continuous BDR node monitoring
|
||||||
|
[2017-07-27 21:08:35] [INFO] monitoring BDR replication status on node "node1" (ID: 1)
|
||||||
|
[2017-07-27 21:08:51] [INFO] monitoring BDR replication status on node "node1" (ID: 1)
|
||||||
|
[2017-07-27 21:09:07] [INFO] monitoring BDR replication status on node "node1" (ID: 1)
|
||||||
|
[2017-07-27 21:09:23] [WARNING] unable to connect to node node2 (ID 2)
|
||||||
|
[2017-07-27 21:09:23] [INFO] checking state of node 2, 0 of 5 attempts
|
||||||
|
[2017-07-27 21:09:23] [INFO] sleeping 1 seconds until next reconnection attempt
|
||||||
|
[2017-07-27 21:09:24] [INFO] checking state of node 2, 1 of 5 attempts
|
||||||
|
[2017-07-27 21:09:24] [INFO] sleeping 1 seconds until next reconnection attempt
|
||||||
|
[2017-07-27 21:09:25] [INFO] checking state of node 2, 2 of 5 attempts
|
||||||
|
[2017-07-27 21:09:25] [INFO] sleeping 1 seconds until next reconnection attempt
|
||||||
|
[2017-07-27 21:09:26] [INFO] checking state of node 2, 3 of 5 attempts
|
||||||
|
[2017-07-27 21:09:26] [INFO] sleeping 1 seconds until next reconnection attempt
|
||||||
|
[2017-07-27 21:09:27] [INFO] checking state of node 2, 4 of 5 attempts
|
||||||
|
[2017-07-27 21:09:27] [INFO] sleeping 1 seconds until next reconnection attempt
|
||||||
|
[2017-07-27 21:09:28] [WARNING] unable to reconnect to node 2 after 5 attempts
|
||||||
|
[2017-07-27 21:09:28] [NOTICE] other node's repmgrd is handling failover
|
||||||
|
[2017-07-27 21:09:28] [INFO] monitoring BDR replication status on node "node1" (ID: 1)
|
||||||
|
[2017-07-27 21:09:28] [DETAIL] monitoring node "node2" (ID: 2) in degraded mode
|
||||||
|
...</programlisting>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
This assumes only the PostgreSQL instance on <literal>node2</literal> has failed. In this case the
|
||||||
|
<application>repmgrd</application> instance running on <literal>node2</literal> has performed the failover. However if
|
||||||
|
the entire server becomes unavailable, <application>repmgrd</application> on <literal>node1</literal> will perform
|
||||||
|
the failover.
|
||||||
|
</para>
|
||||||
|
</sect1>
|
||||||
|
<sect1 id="bdr-node-recovery" xreflabel="Node recovery">
|
||||||
|
<title>Node recovery</title>
|
||||||
|
<para>
|
||||||
|
Following failure of a BDR node, if the node subsequently becomes available again,
|
||||||
|
a <varname>bdr_recovery</varname> event will be generated. This could potentially be used to
|
||||||
|
reconfigure PgBouncer automatically to bring the node back into the available pool,
|
||||||
|
however it would be prudent to manually verify the node's status before
|
||||||
|
exposing it to the application.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
If the failed node comes back up and connects correctly, output similar to this
|
||||||
|
will be visible in the <application>repmgrd</application> log:
|
||||||
|
<programlisting>
|
||||||
|
[2017-07-27 21:25:30] [DETAIL] monitoring node "node2" (ID: 2) in degraded mode
|
||||||
|
[2017-07-27 21:25:46] [INFO] monitoring BDR replication status on node "node2" (ID: 2)
|
||||||
|
[2017-07-27 21:25:46] [DETAIL] monitoring node "node2" (ID: 2) in degraded mode
|
||||||
|
[2017-07-27 21:25:55] [INFO] active replication slot for node "node1" found after 1 seconds
|
||||||
|
[2017-07-27 21:25:55] [NOTICE] node "node2" (ID: 2) has recovered after 986 seconds</programlisting>
|
||||||
|
</para>
|
||||||
|
</sect1>
|
||||||
|
|
||||||
|
<sect1 id="bdr-complete-shutdown" xreflabel="Shutdown of both nodes">
|
||||||
|
<title>Shutdown of both nodes</title>
|
||||||
|
<para>
|
||||||
|
If both PostgreSQL instances are shut down, <application>repmgrd</application> will try and handle the
|
||||||
|
situation as gracefully as possible, though with no failover candidates available
|
||||||
|
there's not much it can do. Should this case ever occur, we recommend shutting
|
||||||
|
down <application>repmgrd</application> on both nodes and restarting it once the PostgreSQL instances
|
||||||
|
are running properly.
|
||||||
|
</para>
|
||||||
|
</sect1>
|
||||||
|
</chapter>
|
||||||
|
|
||||||
971
doc/repmgrd-configuration.sgml
Normal file
971
doc/repmgrd-configuration.sgml
Normal file
@@ -0,0 +1,971 @@
|
|||||||
|
<chapter id="repmgrd-configuration">
|
||||||
|
|
||||||
|
<indexterm>
|
||||||
|
<primary>repmgrd</primary>
|
||||||
|
<secondary>configuration</secondary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<title>repmgrd setup and configuration</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
<application>repmgrd</application> is a daemon which runs on each PostgreSQL node,
|
||||||
|
monitoring the local node, and (unless it's the primary node) the upstream server
|
||||||
|
(the primary server or with cascading replication, another standby) which it's
|
||||||
|
connected to.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
<application>repmgrd</application> can be configured to provide failover
|
||||||
|
capability in case the primary upstream node becomes unreachable, and/or
|
||||||
|
provide monitoring data to the &repmgr; metadatabase.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<sect1 id="repmgrd-basic-configuration">
|
||||||
|
<title>repmgrd configuration</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
To use <application>repmgrd</application>, its associated function library <emphasis>must</emphasis> be
|
||||||
|
included via <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/runtime-config-client.html#GUC-SHARED-PRELOAD-LIBRARIES">PostgreSQL documentation</ulink>.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
The following configuraton options apply to <application>repmgrd</application> in all circumstances:
|
||||||
|
</para>
|
||||||
|
<variablelist>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
|
||||||
|
<indexterm>
|
||||||
|
<primary>monitor_interval_secs</primary>
|
||||||
|
</indexterm>
|
||||||
|
<term><option>monitor_interval_secs</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
The interval (in seconds, default: <literal>2</literal>) to check the availability of the upstream node.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry id="connection-check-type">
|
||||||
|
|
||||||
|
<indexterm>
|
||||||
|
<primary>connection_check_type</primary>
|
||||||
|
</indexterm>
|
||||||
|
<term><option>connection_check_type</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
The option <option>connection_check_type</option> is used to select the method
|
||||||
|
<application>repmgrd</application> uses to determine whether the upstream node is available.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Possible values are:
|
||||||
|
<itemizedlist spacing="compact" mark="bullet">
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
<literal>ping</literal> (default) - uses <command>PQping()</command> to
|
||||||
|
determine server availability
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
<literal>connection</literal> - determines server availability
|
||||||
|
by attempt ingto make a new connection to the upstream node
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
<literal>query</literal> - determines server availability
|
||||||
|
by executing an SQL statement on the node via the existing connection
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
</itemizedlist>
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<indexterm>
|
||||||
|
<primary>reconnect_attempts</primary>
|
||||||
|
</indexterm>
|
||||||
|
<term><option>reconnect_attempts</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
The number of attempts (default: <literal>6</literal>) will be made to reconnect to an unreachable
|
||||||
|
upstream node before initiating a failover.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
There will be an interval of <option>reconnect_interval</option> seconds between each reconnection
|
||||||
|
attempt.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<indexterm>
|
||||||
|
<primary>reconnect_interval</primary>
|
||||||
|
</indexterm>
|
||||||
|
<term><option>reconnect_interval</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Interval (in seconds, default: <literal>10</literal>) between attempts to reconnect to an unreachable
|
||||||
|
upstream node.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The number of reconnection attempts is defined by the parameter <option>reconnect_attempts</option>.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<indexterm>
|
||||||
|
<primary>degraded_monitoring_timeout</primary>
|
||||||
|
</indexterm>
|
||||||
|
<term><option>degraded_monitoring_timeout</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Interval (in seconds) after which <application>repmgrd</application> will terminate if
|
||||||
|
either of the servers (local node and or upstream node) being monitored is no longer available
|
||||||
|
(<link linkend="repmgrd-degraded-monitoring">degraded monitoring mode</link>).
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
<literal>-1</literal> (default) disables this timeout completely.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
</variablelist>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
See also <filename><ulink url="https://raw.githubusercontent.com/2ndQuadrant/repmgr/master/repmgr.conf.sample">repmgr.conf.sample</ulink></filename> for an annotated sample configuration file.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<sect2 id="repmgrd-automatic-failover-configuration">
|
||||||
|
<title>Required configuration for automatic failover</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
The following <application>repmgrd</application> options <emphasis>must</emphasis> be set in
|
||||||
|
<filename>repmgr.conf</filename>:
|
||||||
|
|
||||||
|
<itemizedlist spacing="compact" mark="bullet">
|
||||||
|
<listitem>
|
||||||
|
<simpara><option>failover</option></simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara><option>promote_command</option></simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara><option>follow_command</option></simpara>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
</para>
|
||||||
|
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Example:
|
||||||
|
<programlisting>
|
||||||
|
failover=automatic
|
||||||
|
promote_command='/usr/bin/repmgr standby promote -f /etc/repmgr.conf --log-to-file'
|
||||||
|
follow_command='/usr/bin/repmgr standby follow -f /etc/repmgr.conf --log-to-file --upstream-node-id=%n'</programlisting>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Details of each option are as follows:
|
||||||
|
</para>
|
||||||
|
<variablelist>
|
||||||
|
<varlistentry>
|
||||||
|
|
||||||
|
<indexterm>
|
||||||
|
<primary>failover</primary>
|
||||||
|
</indexterm>
|
||||||
|
<term><option>failover</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<option>failover</option> can be one of <literal>automatic</literal> or <literal>manual</literal>.
|
||||||
|
</para>
|
||||||
|
<note>
|
||||||
|
<para>
|
||||||
|
If <option>failover</option> is set to <literal>manual</literal>, <application>repmgrd</application>
|
||||||
|
will not take any action if a failover situation is detected, and the node may need to
|
||||||
|
be modified manually (e.g. by executing <command><link linkend="repmgr-standby-follow">repmgr standby follow</link></command>).
|
||||||
|
</para>
|
||||||
|
</note>
|
||||||
|
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<indexterm>
|
||||||
|
<primary>promote_command</primary>
|
||||||
|
</indexterm>
|
||||||
|
<term><option>promote_command</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
The program or script defined in <option>promote_command</option> will be executed
|
||||||
|
in a failover situation when <application>repmgrd</application> determines that
|
||||||
|
the current node is to become the new primary node.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Normally <option>promote_command</option> is set as &repmgr;'s
|
||||||
|
<command><link linkend="repmgr-standby-promote">repmgr standby promote</link></command> command.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
It is also possible to provide a shell script to e.g. perform user-defined tasks
|
||||||
|
before promoting the current node. In this case the script <emphasis>must</emphasis>
|
||||||
|
at some point execute <command><link linkend="repmgr-standby-promote">repmgr standby promote</link></command>
|
||||||
|
to promote the node; if this is not done, &repmgr; metadata will not be updated and
|
||||||
|
&repmgr; will no longer function reliably.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Example:
|
||||||
|
<programlisting>
|
||||||
|
promote_command='/usr/bin/repmgr standby promote -f /etc/repmgr.conf --log-to-file'</programlisting>
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Note that the <literal>--log-to-file</literal> option will cause
|
||||||
|
output generated by the &repmgr; command, when executed by <application>repmgrd</application>,
|
||||||
|
to be logged to the same destination configured to receive log output for <application>repmgrd</application>.
|
||||||
|
</para>
|
||||||
|
<note>
|
||||||
|
<para>
|
||||||
|
&repmgr; will not apply <option>pg_bindir</option> when executing <option>promote_command</option>
|
||||||
|
or <option>follow_command</option>; these can be user-defined scripts so must always be
|
||||||
|
specified with the full path.
|
||||||
|
</para>
|
||||||
|
</note>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<indexterm>
|
||||||
|
<primary>follow_command</primary>
|
||||||
|
</indexterm>
|
||||||
|
<term><option>follow_command</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
The program or script defined in <option>follow_command</option> will be executed
|
||||||
|
in a failover situation when <application>repmgrd</application> determines that
|
||||||
|
the current node is to follow the new primary node.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Normally <option>follow_command</option> is set as &repmgr;'s
|
||||||
|
<command><link linkend="repmgr-standby-follow">repmgr standby follow</link></command> command.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The <option>follow_command</option> parameter
|
||||||
|
should provide the <literal>--upstream-node-id=%n</literal>
|
||||||
|
option to <command>repmgr standby follow</command>; the <literal>%n</literal> will be replaced by
|
||||||
|
<application>repmgrd</application> with the ID of the new primary node. If this is not provided,
|
||||||
|
<command>repmgr standby follow</command> 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>
|
||||||
|
<para>
|
||||||
|
It is also possible to provide a shell script to e.g. perform user-defined tasks
|
||||||
|
before promoting the current node. In this case the script <emphasis>must</emphasis>
|
||||||
|
at some point execute <command><link linkend="repmgr-standby-follow">repmgr standby follow</link></command>
|
||||||
|
to promote the node; if this is not done, &repmgr; metadata will not be updated and
|
||||||
|
&repmgr; will no longer function reliably.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Example:
|
||||||
|
<programlisting>
|
||||||
|
follow_command='/usr/bin/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 <application>repmgrd</application>,
|
||||||
|
to be logged to the same destination configured to receive log output for <application>repmgrd</application>.
|
||||||
|
</para>
|
||||||
|
<note>
|
||||||
|
<para>
|
||||||
|
&repmgr; will not apply <option>pg_bindir</option> when executing <option>promote_command</option>
|
||||||
|
or <option>follow_command</option>; these can be user-defined scripts so must always be
|
||||||
|
specified with the full path.
|
||||||
|
</para>
|
||||||
|
</note>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
</variablelist>
|
||||||
|
|
||||||
|
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
<sect2 id="repmgrd-automatic-failover-configuration-optional">
|
||||||
|
<title>Optional configuration for automatic failover</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
The following configuraton options can be use to fine-tune automatic failover:
|
||||||
|
</para>
|
||||||
|
<variablelist>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<indexterm>
|
||||||
|
<primary>priority</primary>
|
||||||
|
</indexterm>
|
||||||
|
<term><option>priority</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Indicates a preferred priority (default: <literal>100</literal>) for promoting nodes;
|
||||||
|
a value of zero prevents the node being promoted to primary.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Note that the priority setting is only applied if two or more nodes are
|
||||||
|
determined as promotion candidates; in that case the node with the
|
||||||
|
higher priority is selected.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<indexterm>
|
||||||
|
<primary>failover_validation_command</primary>
|
||||||
|
</indexterm>
|
||||||
|
<term><option>failover_validation_command</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
User-defined script to execute for an external mechanism to validate the failover
|
||||||
|
decision made by <application>repmgrd</application>.
|
||||||
|
</para>
|
||||||
|
<note>
|
||||||
|
<para>
|
||||||
|
This option <emphasis>must</emphasis> be identically configured
|
||||||
|
on all nodes.
|
||||||
|
</para>
|
||||||
|
</note>
|
||||||
|
<para>
|
||||||
|
One or both of the following parameter placeholders
|
||||||
|
should be provided, which will be replaced by repmgrd with the appropriate
|
||||||
|
value:
|
||||||
|
<itemizedlist spacing="compact" mark="bullet">
|
||||||
|
<listitem>
|
||||||
|
<simpara><literal>%n</literal>: node ID</simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara><literal>%a</literal>: node name</simpara>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
See also: <link linkend="repmgrd-failover-validation">Failover validation</link>.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
|
||||||
|
<indexterm>
|
||||||
|
<primary>standby_disconnect_on_failover</primary>
|
||||||
|
</indexterm>
|
||||||
|
<term><option>standby_disconnect_on_failover</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
In a failover situation, disconnect the local node's WAL receiver.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
This option is available from PostgreSQL 9.5 and later.
|
||||||
|
</para>
|
||||||
|
<note>
|
||||||
|
<para>
|
||||||
|
This option <emphasis>must</emphasis> be identically configured
|
||||||
|
on all nodes.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Additionally the &repmgr; user <emphasis>must</emphasis> be a superuser
|
||||||
|
for this option.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
<application>repmgrd</application> will refuse to start if this option is set
|
||||||
|
but either of these prerequisites is not met.
|
||||||
|
</para>
|
||||||
|
</note>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
See also: <link linkend="repmgrd-standby-disconnection-on-failover">Standby disconnection on failover</link>.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
</variablelist>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
The following options can be used to further fine-tune failover behaviour.
|
||||||
|
In practice it's unlikely these will need to be changed from their default
|
||||||
|
values, but are available as configuration options should the need arise.
|
||||||
|
</para>
|
||||||
|
<variablelist>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<indexterm>
|
||||||
|
<primary>election_rerun_interval</primary>
|
||||||
|
</indexterm>
|
||||||
|
<term><option>election_rerun_interval</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
If <option>failover_validation_command</option> is set, and the command returns
|
||||||
|
an error, pause the specified amount of seconds (default: 15) before rerunning the election.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<indexterm>
|
||||||
|
<primary>sibling_nodes_disconnect_timeout</primary>
|
||||||
|
</indexterm>
|
||||||
|
<term><option>sibling_nodes_disconnect_timeout</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
If <option>standby_disconnect_on_failover</option> is <literal>true</literal>, the
|
||||||
|
maximum length of time (in seconds, default: <literal>30</literal>)
|
||||||
|
to wait for other standbys to confirm they have disconnected their
|
||||||
|
WAL receivers.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
<sect2 id="postgresql-service-configuration">
|
||||||
|
<indexterm>
|
||||||
|
<primary>repmgrd</primary>
|
||||||
|
<secondary>PostgreSQL service configuration</secondary>
|
||||||
|
</indexterm>
|
||||||
|
<title>PostgreSQL service configuration</title>
|
||||||
|
<para>
|
||||||
|
If using automatic failover, currently <application>repmgrd</application> will need to execute
|
||||||
|
<link linkend="repmgr-standby-follow"><command>repmgr standby follow</command></link>
|
||||||
|
to restart PostgreSQL on standbys to have them follow a new primary.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
To ensure this happens smoothly, it's essential to provide the appropriate system/service restart
|
||||||
|
command appropriate to your operating system via <varname>service_restart_command</varname>
|
||||||
|
in <filename>repmgr.conf</filename>. If you don't do this, <application>repmgrd</application>
|
||||||
|
will default to using <command>pg_ctl</command>, which can result in unexpected problems,
|
||||||
|
particularly on <application>systemd</application>-based systems.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
For more details, see <xref linkend="configuration-file-service-commands">.
|
||||||
|
</para>
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
<sect2 id="repmgrd-service-configuration">
|
||||||
|
<indexterm>
|
||||||
|
<primary>repmgrd</primary>
|
||||||
|
<secondary>repmgrd service configuration</secondary>
|
||||||
|
</indexterm>
|
||||||
|
<title>repmgrd service configuration</title>
|
||||||
|
<para>
|
||||||
|
If you are intending to use the <link linkend="repmgr-daemon-start"><command>repmgr daemon start</command></link>
|
||||||
|
and <link linkend="repmgr-daemon-stop"><command>repmgr daemon stop</command></link> commands, the following
|
||||||
|
parameters <emphasis>must</emphasis> be set in <filename>repmgr.conf</filename>:
|
||||||
|
<itemizedlist spacing="compact" mark="bullet">
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara><varname>repmgrd_service_start_command</varname></simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara><varname>repmgrd_service_stop_command</varname></simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
</itemizedlist>
|
||||||
|
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Example (for &repmgr; with PostgreSQL 11 on CentOS 7):
|
||||||
|
<programlisting>
|
||||||
|
repmgrd_service_start_command='sudo systemctl repmgr11 start'
|
||||||
|
repmgrd_service_stop_command='sudo systemctl repmgr11 stop'
|
||||||
|
</programlisting>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
For more details see the reference page for each command.
|
||||||
|
</para>
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
|
||||||
|
<sect2 id="repmgrd-monitoring-configuration" xreflabel="repmgrd monitoring configuration">
|
||||||
|
<indexterm>
|
||||||
|
<primary>repmgrd</primary>
|
||||||
|
<secondary>monitoring configuration</secondary>
|
||||||
|
</indexterm>
|
||||||
|
<title>Monitoring configuration</title>
|
||||||
|
<para>
|
||||||
|
To enable monitoring, set:
|
||||||
|
<programlisting>
|
||||||
|
monitoring_history=yes</programlisting>
|
||||||
|
in <filename>repmgr.conf</filename>.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Monitoring data is written at the interval defined by
|
||||||
|
the option <option>monitor_interval_secs</option> (see above).
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
For more details on monitoring, see <xref linkend="repmgrd-monitoring">.
|
||||||
|
</para>
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
<sect2 id="repmgrd-reloading-configuration"xreflabel="reloading repmgrd configuration">
|
||||||
|
<indexterm>
|
||||||
|
<primary>repmgrd</primary>
|
||||||
|
<secondary>applying configuration changes</secondary>
|
||||||
|
</indexterm>
|
||||||
|
<title>Applying configuration changes to repmgrd</title>
|
||||||
|
<para>
|
||||||
|
To apply configuration file changes to a running <application>repmgrd</application>
|
||||||
|
daemon, execute the operating system's <application>repmgrd</application> service reload command
|
||||||
|
(see <xref linkend="appendix-packages"> for examples),
|
||||||
|
or for instances which were manually started, execute <command>kill -HUP</command>, e.g.
|
||||||
|
<command>kill -HUP `cat /tmp/repmgrd.pid`</command>.
|
||||||
|
</para>
|
||||||
|
<tip>
|
||||||
|
<para>
|
||||||
|
Check the <application>repmgrd</application> log to see what changes were
|
||||||
|
applied, or if any issues were encountered when reloading the configuration.
|
||||||
|
</para>
|
||||||
|
</tip>
|
||||||
|
<para>
|
||||||
|
Note that only the following subset of configuration file parameters can be changed on a
|
||||||
|
running <application>repmgrd</application> daemon:
|
||||||
|
</para>
|
||||||
|
<itemizedlist spacing="compact" mark="bullet">
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
<varname>async_query_timeout</varname>
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
<varname>bdr_local_monitoring_only</varname>
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
<varname>bdr_recovery_timeout</varname>
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
<varname>connection_check_type</varname>
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
<varname>conninfo</varname>
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
<varname>degraded_monitoring_timeout</varname>
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
<varname>event_notification_command</varname>
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
<varname>event_notifications</varname>
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
<varname>failover_validation_command</varname>
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
<varname>failover</varname>
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
<varname>follow_command</varname>
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
<varname>log_facility</varname>
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
<varname>log_file</varname>
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
<varname>log_level</varname>
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
<varname>log_status_interval</varname>
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
<varname>monitor_interval_secs</varname>
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
<varname>monitoring_history</varname>
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
<varname>primary_notification_timeout</varname>
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
<varname>promote_command</varname>
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
<varname>reconnect_attempts</varname>
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
<varname>reconnect_interval</varname>
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
<varname>retry_promote_interval_secs</varname>
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
<varname>repmgrd_standby_startup_timeout</varname>
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
<varname>sibling_nodes_disconnect_timeout</varname>
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
<varname>standby_disconnect_on_failover</varname>
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
</itemizedlist>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
The following set of configuration file parameters must be updated via
|
||||||
|
<command><link linkend="repmgr-standby-register">repmgr standby register --force</link></command>,
|
||||||
|
as they require changes to the <literal>repmgr.nodes</literal> table so they are visible to
|
||||||
|
all nodes in the replication cluster:
|
||||||
|
</para>
|
||||||
|
<itemizedlist spacing="compact" mark="bullet">
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
<varname>node_id</varname>
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
<varname>node_name</varname>
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
<varname>data_directory</varname>
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
<varname>location</varname>
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
<varname>priority</varname>
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
</itemizedlist>
|
||||||
|
|
||||||
|
<note>
|
||||||
|
<para>
|
||||||
|
After executing <command><link linkend="repmgr-standby-register">repmgr standby register --force</link></command>,
|
||||||
|
<application>repmgrd</application> <emphasis>must</emphasis> be restarted for the changes to take effect.
|
||||||
|
</para>
|
||||||
|
</note>
|
||||||
|
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
</sect1>
|
||||||
|
|
||||||
|
<sect1 id="repmgrd-daemon" xreflabel="repmgrd daemon">
|
||||||
|
<indexterm>
|
||||||
|
<primary>repmgrd</primary>
|
||||||
|
<secondary>starting and stopping</secondary>
|
||||||
|
</indexterm>
|
||||||
|
<title>repmgrd daemon</title>
|
||||||
|
<para>
|
||||||
|
If installed from a package, the <application>repmgrd</application> can be started
|
||||||
|
via the operating system's service command, e.g. in <application>systemd</application>
|
||||||
|
using <command>systemctl</command>.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
See appendix <xref linkend="appendix-packages"> for details of service commands
|
||||||
|
for different distributions.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The commands <link linkend="repmgr-daemon-start"><command>repmgr daemon start</command></link> and
|
||||||
|
<link linkend="repmgr-daemon-stop"><command>repmgr daemon stop</command></link> can be used
|
||||||
|
as convenience wrappers to start and stop <application>repmgrd</application>.
|
||||||
|
</para>
|
||||||
|
<important>
|
||||||
|
<para>
|
||||||
|
<link linkend="repmgr-daemon-start"><command>repmgr daemon start</command></link> and
|
||||||
|
<link linkend="repmgr-daemon-stop"><command>repmgr daemon stop</command></link> require
|
||||||
|
that the appropriate start/stop commands are configured as
|
||||||
|
<varname>repmgrd_service_start_command</varname> and <varname>repmgrd_service_stop_command</varname>
|
||||||
|
in <filename>repmgr.conf</filename>.
|
||||||
|
</para>
|
||||||
|
</important>
|
||||||
|
<para>
|
||||||
|
<application>repmgrd</application> can be started manually like this:
|
||||||
|
<programlisting>
|
||||||
|
repmgrd -f /etc/repmgr.conf --pid-file /tmp/repmgrd.pid</programlisting>
|
||||||
|
and stopped with <command>kill `cat /tmp/repmgrd.pid`</command>. Adjust paths as appropriate.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<sect2 id="repmgrd-pid-file" xreflabel="repmgrd's PID file">
|
||||||
|
<indexterm>
|
||||||
|
<primary>repmgrd</primary>
|
||||||
|
<secondary>PID file</secondary>
|
||||||
|
</indexterm>
|
||||||
|
<indexterm>
|
||||||
|
<primary>PID file</primary>
|
||||||
|
<secondary>repmgrd</secondary>
|
||||||
|
</indexterm>
|
||||||
|
<title>repmgrd's PID file</title>
|
||||||
|
<para>
|
||||||
|
<application>repmgrd</application> will generate a PID file by default.
|
||||||
|
</para>
|
||||||
|
<note>
|
||||||
|
<simpara>
|
||||||
|
This is a behaviour change from previous versions (earlier than 4.1), where
|
||||||
|
the PID file had to be explicitly specified with the command line
|
||||||
|
parameter <option>--pid-file</option>.
|
||||||
|
</simpara>
|
||||||
|
</note>
|
||||||
|
<para>
|
||||||
|
The PID file can be specified in <filename>repmgr.conf</filename> with the configuration
|
||||||
|
parameter <varname>repmgrd_pid_file</varname>.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
It can also be specified on the command line (as in previous versions) with
|
||||||
|
the command line parameter <option>--pid-file</option>. Note this will override
|
||||||
|
any value set in <filename>repmgr.conf</filename> with <varname>repmgrd_pid_file</varname>.
|
||||||
|
<option>--pid-file</option> may be deprecated in future releases.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
If a PID file location was specified by the package maintainer, <application>repmgrd</application>
|
||||||
|
will use that. This only applies if &repmgr; was installed from a package and the package
|
||||||
|
maintainer has specified the PID file location.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
If none of the above apply, <application>repmgrd</application> will create a PID file
|
||||||
|
in the operating system's temporary directory (as setermined by the environment variable
|
||||||
|
<varname>TMPDIR</varname>, or if that is not set, will use <filename>/tmp</filename>).
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
To prevent a PID file being generated at all, provide the command line option
|
||||||
|
<option>--no-pid-file</option>.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
To see which PID file <application>repmgrd</application> would use, execute <application>repmgrd</application>
|
||||||
|
with the option <option>--show-pid-file</option>. <application>repmgrd</application>
|
||||||
|
will not start if this option is provided. Note that the value shown is the
|
||||||
|
file <application>repmgrd</application> would use next time it starts, and is
|
||||||
|
not necessarily the PID file currently in use.
|
||||||
|
</para>
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
<sect2 id="repmgrd-configuration-debian-ubuntu">
|
||||||
|
<indexterm>
|
||||||
|
<primary>repmgrd</primary>
|
||||||
|
<secondary>Debian/Ubuntu and daemon configuration</secondary>
|
||||||
|
</indexterm>
|
||||||
|
<indexterm>
|
||||||
|
<primary>Debian/Ubuntu</primary>
|
||||||
|
<secondary>repmgrd daemon configuration</secondary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<title>repmgrd daemon configuration on Debian/Ubuntu</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
If &repmgr; was installed from Debian/Ubuntu packages, additional configuration
|
||||||
|
is required before <application>repmgrd</application> is started as a daemon.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
This is done via the file <filename>/etc/default/repmgrd</filename>, which by default
|
||||||
|
looks like this:
|
||||||
|
<programlisting>
|
||||||
|
# default settings for repmgrd. This file is source by /bin/sh from
|
||||||
|
# /etc/init.d/repmgrd
|
||||||
|
|
||||||
|
# disable repmgrd by default so it won't get started upon installation
|
||||||
|
# valid values: yes/no
|
||||||
|
REPMGRD_ENABLED=no
|
||||||
|
|
||||||
|
# configuration file (required)
|
||||||
|
#REPMGRD_CONF="/path/to/repmgr.conf"
|
||||||
|
|
||||||
|
# additional options
|
||||||
|
REPMGRD_OPTS="--daemonize=false"
|
||||||
|
|
||||||
|
# user to run repmgrd as
|
||||||
|
#REPMGRD_USER=postgres
|
||||||
|
|
||||||
|
# repmgrd binary
|
||||||
|
#REPMGRD_BIN=/usr/bin/repmgrd
|
||||||
|
|
||||||
|
# pid file
|
||||||
|
#REPMGRD_PIDFILE=/var/run/repmgrd.pid</programlisting>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Set <varname>REPMGRD_ENABLED</varname> to <literal>yes</literal>, and <varname>REPMGRD_CONF</varname>
|
||||||
|
to the <filename>repmgr.conf</filename> file you are using.
|
||||||
|
</para>
|
||||||
|
<tip>
|
||||||
|
<para>
|
||||||
|
See <xref linkend="packages-debian-ubuntu"> for details of the Debian/Ubuntu packages and
|
||||||
|
typical file locations (including <filename>repmgr.conf</filename>).
|
||||||
|
</para>
|
||||||
|
</tip>
|
||||||
|
<para>
|
||||||
|
From <application>repmgrd</application> 4.1, ensure <varname>REPMGRD_OPTS</varname> includes
|
||||||
|
<option>--daemonize=false</option>, as daemonization is handled by the service command.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
If using <application>systemd</application>, you may need to execute <command>systemctl daemon-reload</command>.
|
||||||
|
Also, if you attempted to start <application>repmgrd</application> using <command>systemctl start repmgrd</command>,
|
||||||
|
you'll need to execute <command>systemctl stop repmgrd</command>. Because that's how <application>systemd</application>
|
||||||
|
rolls.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
</sect2>
|
||||||
|
</sect1>
|
||||||
|
|
||||||
|
<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/libpq-connect.html#LIBPQ-PARAMKEYWORDS">PostgreSQL documentation</ulink>.
|
||||||
|
</para>
|
||||||
|
</sect1>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<sect1 id="repmgrd-log-rotation">
|
||||||
|
<indexterm>
|
||||||
|
<primary>log rotation</primary>
|
||||||
|
<secondary>repmgrd</secondary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<indexterm>
|
||||||
|
<primary>repmgrd</primary>
|
||||||
|
<secondary>log rotation</secondary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<title>repmgrd log rotation</title>
|
||||||
|
<para>
|
||||||
|
To ensure the current <application>repmgrd</application> logfile
|
||||||
|
(specified in <filename>repmgr.conf</filename> with the parameter
|
||||||
|
<option>log_file</option>) 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/repmgr/repmgrd.log {
|
||||||
|
missingok
|
||||||
|
compress
|
||||||
|
rotate 52
|
||||||
|
maxsize 100M
|
||||||
|
weekly
|
||||||
|
create 0600 postgres postgres
|
||||||
|
postrotate
|
||||||
|
/usr/bin/killall -HUP repmgrd
|
||||||
|
endscript
|
||||||
|
}</programlisting>
|
||||||
|
</para>
|
||||||
|
|
||||||
|
</sect1>
|
||||||
|
</chapter>
|
||||||
386
doc/repmgrd-operation.sgml
Normal file
386
doc/repmgrd-operation.sgml
Normal file
@@ -0,0 +1,386 @@
|
|||||||
|
<chapter id="repmgrd-operation" xreflabel="repmgrd operation">
|
||||||
|
<indexterm>
|
||||||
|
<primary>repmgrd</primary>
|
||||||
|
<secondary>operation</secondary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<title>repmgrd operation</title>
|
||||||
|
|
||||||
|
|
||||||
|
<sect1 id="repmgrd-pausing">
|
||||||
|
|
||||||
|
<indexterm>
|
||||||
|
<primary>repmgrd</primary>
|
||||||
|
<secondary>pausing</secondary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<indexterm>
|
||||||
|
<primary>pausing repmgrd</primary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<title>Pausing repmgrd</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
In normal operation, <application>repmgrd</application> monitors the state of the
|
||||||
|
PostgreSQL node it is running on, and will take appropriate action if problems
|
||||||
|
are detected, e.g. (if so configured) promote the node to primary, if the existing
|
||||||
|
primary has been determined as failed.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
However, <application>repmgrd</application> is unable to distinguish between
|
||||||
|
planned outages (such as performing a <link linkend="performing-switchover">switchover</link>
|
||||||
|
or installing PostgreSQL maintenance released), and an actual server outage. In versions prior to
|
||||||
|
&repmgr; 4.2 it was necessary to stop <application>repmgrd</application> on all nodes (or at least
|
||||||
|
on all nodes where <application>repmgrd</application> is
|
||||||
|
<link linkend="repmgrd-automatic-failover">configured for automatic failover</link>)
|
||||||
|
to prevent <application>repmgrd</application> from making unintentional changes to the
|
||||||
|
replication cluster.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
From <link linkend="release-4.2">&repmgr; 4.2</link>, <application>repmgrd</application>
|
||||||
|
can now be "paused", i.e. instructed not to take any action such as performing a failover.
|
||||||
|
This can be done from any node in the cluster, removing the need to stop/restart
|
||||||
|
each <application>repmgrd</application> individually.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<note>
|
||||||
|
<para>
|
||||||
|
For major PostgreSQL upgrades, e.g. from PostgreSQL 10 to PostgreSQL 11,
|
||||||
|
<application>repmgrd</application> should be shut down completely and only started up
|
||||||
|
once the &repmgr; packages for the new PostgreSQL major version have been installed.
|
||||||
|
</para>
|
||||||
|
</note>
|
||||||
|
|
||||||
|
<sect2 id="repmgrd-pausing-prerequisites">
|
||||||
|
<title>Prerequisites for pausing <application>repmgrd</application></title>
|
||||||
|
<para>
|
||||||
|
In order to be able to pause/unpause <application>repmgrd</application>, following
|
||||||
|
prerequisites must be met:
|
||||||
|
<itemizedlist spacing="compact" mark="bullet">
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara><link linkend="release-4.2">&repmgr; 4.2</link> or later must be installed on all nodes.</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>The same major &repmgr; version (e.g. 4.2) must be installed on all nodes (and preferably the same minor version).</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
PostgreSQL on all nodes must be accessible from the node where the
|
||||||
|
<literal>pause</literal>/<literal>unpause</literal> operation is executed, using the
|
||||||
|
<varname>conninfo</varname> string shown by <link linkend="repmgr-cluster-show"><command>repmgr cluster show</command></link>.
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
</para>
|
||||||
|
<note>
|
||||||
|
<para>
|
||||||
|
These conditions are required for normal &repmgr; operation in any case.
|
||||||
|
</para>
|
||||||
|
</note>
|
||||||
|
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
<sect2 id="repmgrd-pausing-execution">
|
||||||
|
<title>Pausing/unpausing <application>repmgrd</application></title>
|
||||||
|
<para>
|
||||||
|
To pause <application>repmgrd</application>, execute <link linkend="repmgr-daemon-pause"><command>repmgr daemon pause</command></link>, e.g.:
|
||||||
|
<programlisting>
|
||||||
|
$ repmgr -f /etc/repmgr.conf daemon pause
|
||||||
|
NOTICE: node 1 (node1) paused
|
||||||
|
NOTICE: node 2 (node2) paused
|
||||||
|
NOTICE: node 3 (node3) paused</programlisting>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The state of <application>repmgrd</application> on each node can be checked with
|
||||||
|
<link linkend="repmgr-daemon-status"><command>repmgr daemon status</command></link>, e.g.:
|
||||||
|
<programlisting>$ repmgr -f /etc/repmgr.conf daemon status
|
||||||
|
ID | Name | Role | Status | repmgrd | PID | Paused?
|
||||||
|
----+-------+---------+---------+---------+------+---------
|
||||||
|
1 | node1 | primary | running | running | 7851 | yes
|
||||||
|
2 | node2 | standby | running | running | 7889 | yes
|
||||||
|
3 | node3 | standby | running | running | 7918 | yes</programlisting>
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<note>
|
||||||
|
<para>
|
||||||
|
If executing a switchover with <link linkend="repmgr-standby-switchover"><command>repmgr standby switchover</command></link>,
|
||||||
|
&repmgr; will automatically pause/unpause <application>repmgrd</application> as part of the switchover process.
|
||||||
|
</para>
|
||||||
|
</note>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
If the primary (in this example, <literal>node1</literal>) is stopped, <application>repmgrd</application>
|
||||||
|
running on one of the standbys (here: <literal>node2</literal>) will react like this:
|
||||||
|
<programlisting>
|
||||||
|
[2018-09-20 12:22:21] [WARNING] unable to connect to upstream node "node1" (node ID: 1)
|
||||||
|
[2018-09-20 12:22:21] [INFO] checking state of node 1, 1 of 5 attempts
|
||||||
|
[2018-09-20 12:22:21] [INFO] sleeping 1 seconds until next reconnection attempt
|
||||||
|
...
|
||||||
|
[2018-09-20 12:22:24] [INFO] sleeping 1 seconds until next reconnection attempt
|
||||||
|
[2018-09-20 12:22:25] [INFO] checking state of node 1, 5 of 5 attempts
|
||||||
|
[2018-09-20 12:22:25] [WARNING] unable to reconnect to node 1 after 5 attempts
|
||||||
|
[2018-09-20 12:22:25] [NOTICE] node is paused
|
||||||
|
[2018-09-20 12:22:33] [INFO] node "node2" (node ID: 2) monitoring upstream node "node1" (node ID: 1) in degraded state
|
||||||
|
[2018-09-20 12:22:33] [DETAIL] repmgrd paused by administrator
|
||||||
|
[2018-09-20 12:22:33] [HINT] execute "repmgr daemon unpause" to resume normal failover mode</programlisting>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
If the primary becomes available again (e.g. following a software upgrade), <application>repmgrd</application>
|
||||||
|
will automatically reconnect, e.g.:
|
||||||
|
<programlisting>
|
||||||
|
[2018-09-20 13:12:41] [NOTICE] reconnected to upstream node 1 after 8 seconds, resuming monitoring</programlisting>
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
To unpause <application>repmgrd</application>, execute <link linkend="repmgr-daemon-unpause"><command>repmgr daemon unpause</command></link>, e.g.:
|
||||||
|
<programlisting>
|
||||||
|
$ repmgr -f /etc/repmgr.conf daemon unpause
|
||||||
|
NOTICE: node 1 (node1) unpaused
|
||||||
|
NOTICE: node 2 (node2) unpaused
|
||||||
|
NOTICE: node 3 (node3) unpaused</programlisting>
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<note>
|
||||||
|
<para>
|
||||||
|
If the previous primary is no longer accessible when <application>repmgrd</application>
|
||||||
|
is unpaused, no failover action will be taken. Instead, a new primary must be manually promoted using
|
||||||
|
<link linkend="repmgr-standby-promote"><command>repmgr standby promote</command></link>,
|
||||||
|
and any standbys attached to the new primary with
|
||||||
|
<link linkend="repmgr-standby-follow"><command>repmgr standby follow</command></link>.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
This is to prevent <link linkend="repmgr-daemon-unpause"><command>repmgr daemon unpause</command></link>
|
||||||
|
resulting in the automatic promotion of a new primary, which may be a problem particularly
|
||||||
|
in larger clusters, where <application>repmgrd</application> could select a different promotion
|
||||||
|
candidate to the one intended by the administrator.
|
||||||
|
</para>
|
||||||
|
</note>
|
||||||
|
</sect2>
|
||||||
|
<sect2 id="repmgrd-pausing-details">
|
||||||
|
<title>Details on the <application>repmgrd</application> pausing mechanism</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
The pause state of each node will be stored over a PostgreSQL restart.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
<link linkend="repmgr-daemon-pause"><command>repmgr daemon pause</command></link> and
|
||||||
|
<link linkend="repmgr-daemon-unpause"><command>repmgr daemon unpause</command></link> can be
|
||||||
|
executed even if <application>repmgrd</application> is not running; in this case,
|
||||||
|
<application>repmgrd</application> will start up in whichever pause state has been set.
|
||||||
|
</para>
|
||||||
|
<note>
|
||||||
|
<para>
|
||||||
|
<link linkend="repmgr-daemon-pause"><command>repmgr daemon pause</command></link> and
|
||||||
|
<link linkend="repmgr-daemon-unpause"><command>repmgr daemon unpause</command></link>
|
||||||
|
<emphasis>do not</emphasis> stop/start <application>repmgrd</application>.
|
||||||
|
</para>
|
||||||
|
</note>
|
||||||
|
</sect2>
|
||||||
|
</sect1>
|
||||||
|
|
||||||
|
<sect1 id="repmgrd-wal-replay-pause">
|
||||||
|
<indexterm>
|
||||||
|
<primary>repmgrd</primary>
|
||||||
|
<secondary>paused WAL replay</secondary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<title>repmgrd and paused WAL replay</title>
|
||||||
|
<para>
|
||||||
|
If WAL replay has been paused (using <command>pg_wal_replay_pause()</command>,
|
||||||
|
on PostgreSQL 9.6 and earlier <command>pg_xlog_replay_pause()</command>),
|
||||||
|
in a failover situation <application>repmgrd</application> will
|
||||||
|
automatically resume WAL replay.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
This is because if WAL replay is paused, but WAL is pending replay,
|
||||||
|
PostgreSQL cannot be promoted until WAL replay is resumed.
|
||||||
|
</para>
|
||||||
|
<note>
|
||||||
|
<para>
|
||||||
|
<command><link linkend="repmgr-standby-promote">repmgr standby promote</link></command>
|
||||||
|
will refuse to promote a node in this state, as the PostgreSQL
|
||||||
|
<command>promote</command> command will not be acted on until
|
||||||
|
WAL replay is resumed, leaving the cluster in a potentially
|
||||||
|
unstable state. In this case it is up to the user to
|
||||||
|
decide whether to resume WAL replay.
|
||||||
|
</para>
|
||||||
|
</note>
|
||||||
|
</sect1>
|
||||||
|
|
||||||
|
<sect1 id="repmgrd-degraded-monitoring" xreflabel="repmgrd degraded monitoring">
|
||||||
|
<indexterm>
|
||||||
|
<primary>repmgrd</primary>
|
||||||
|
<secondary>degraded monitoring</secondary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<indexterm>
|
||||||
|
<primary>degraded monitoring</primary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<title>"degraded monitoring" mode</title>
|
||||||
|
<para>
|
||||||
|
In certain circumstances, <application>repmgrd</application> is not able to fulfill its primary mission
|
||||||
|
of monitoring the node's upstream server. In these cases it enters "degraded monitoring"
|
||||||
|
mode, where <application>repmgrd</application> 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 (and no other node has been promoted as primary)</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 <application>repmgrd</application> will terminate.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<note>
|
||||||
|
<para>
|
||||||
|
If <application>repmgrd</application> is monitoring a primary mode which has been stopped
|
||||||
|
and manually restarted as a standby attached to a new primary, it will automatically detect
|
||||||
|
the status change and update the node record to reflect the node's new status
|
||||||
|
as an active standby. It will then resume monitoring the node as a standby.
|
||||||
|
</para>
|
||||||
|
</note>
|
||||||
|
</sect1>
|
||||||
|
|
||||||
|
|
||||||
|
<sect1 id="repmgrd-monitoring" xreflabel="Storing monitoring data">
|
||||||
|
<indexterm>
|
||||||
|
<primary>repmgrd</primary>
|
||||||
|
<secondary>monitoring</secondary>
|
||||||
|
</indexterm>
|
||||||
|
<indexterm>
|
||||||
|
<primary>monitoring</primary>
|
||||||
|
<secondary>with repmgrd</secondary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<title>Storing monitoring data</title>
|
||||||
|
<para>
|
||||||
|
When <application>repmgrd</application> 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 <application>repmgrd</application> 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>
|
||||||
|
</sect1>
|
||||||
|
|
||||||
|
|
||||||
|
</chapter>
|
||||||
187
doc/repmgrd-overview.sgml
Normal file
187
doc/repmgrd-overview.sgml
Normal file
@@ -0,0 +1,187 @@
|
|||||||
|
<chapter id="repmgrd-overview" xreflabel="repmgrd overview">
|
||||||
|
<indexterm>
|
||||||
|
<primary>repmgrd</primary>
|
||||||
|
<secondary>overview</secondary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<title>repmgrd overview</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
<application>repmgrd</application> ("<literal>replication manager daemon</literal>")
|
||||||
|
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>
|
||||||
|
<para>
|
||||||
|
<application>repmgrd</application> is designed to be straightforward to set up
|
||||||
|
and does not require additional external infrastructure.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Functionality provided by <application>repmgrd</application> includes:
|
||||||
|
<itemizedlist spacing="compact" mark="bullet">
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
wide range of <link linkend="repmgrd-basic-configuration">configuration options</link>
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
option to execute custom scripts ("<link linkend="event-notifications">event notifications</link>
|
||||||
|
at different points in the failover sequence
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
ability to <link linkend="repmgrd-pausing">pause repmgrd</link>
|
||||||
|
operation on all nodes with a
|
||||||
|
<link linkend="repmgr-daemon-pause"><command>single command</command></link>
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
optional <link linkend="repmgrd-witness-server">witness server</link>
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
"location" configuration option to restrict
|
||||||
|
potential promotion candidates to a single location
|
||||||
|
(e.g. when nodes are spread over multiple data centres)
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
<link linkend="connection-check-type">choice of method</link> to determine node availability
|
||||||
|
(PostgreSQL ping, query execution or new connection)
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
retention of monitoring statistics (optional)
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
|
||||||
|
</itemizedlist>
|
||||||
|
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<sect1 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 --compact
|
||||||
|
ID | Name | Role | Status | Upstream | Location | Prio.
|
||||||
|
----+-------+---------+-----------+----------+----------+-------
|
||||||
|
1 | node1 | primary | * running | | default | 100
|
||||||
|
2 | node2 | standby | running | node1 | default | 100
|
||||||
|
3 | node3 | standby | running | node1 | default | 100</programlisting>
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<tip>
|
||||||
|
<para>
|
||||||
|
See section <link linkend="repmgrd-automatic-failover-configuration">Required configuration for automatic failover</link>
|
||||||
|
for an example of minimal <filename>repmgr.conf</filename> file settings suitable for use with <application>repmgrd</application>.
|
||||||
|
</para>
|
||||||
|
</tip>
|
||||||
|
<para>
|
||||||
|
Start <application>repmgrd</application> 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>
|
||||||
|
[2019-03-15 06:32:05] [NOTICE] repmgrd (repmgrd 4.3) starting up
|
||||||
|
[2019-03-15 06:32:05] [INFO] connecting to database "host=node2 dbname=repmgr user=repmgr connect_timeout=2"
|
||||||
|
INFO: set_repmgrd_pid(): provided pidfile is /var/run/repmgr/repmgrd-11.pid
|
||||||
|
[2019-03-15 06:32:05] [NOTICE] starting monitoring of node "node2" (ID: 2)
|
||||||
|
[2019-03-15 06:32:05] [INFO] monitoring connection to upstream node "node1" (node ID: 1)</programlisting>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Each <application>repmgrd</application> 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 | 2019-03-14 04:17:30 | monitoring connection to upstream node "node1" (node ID: 1)
|
||||||
|
2 | node2 | repmgrd_start | t | 2019-03-14 04:11:47 | monitoring connection to upstream node "node1" (node ID: 1)
|
||||||
|
1 | node1 | repmgrd_start | t | 2019-03-14 04:04:31 | 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 <application>repmgrd</application> log
|
||||||
|
files as each <application>repmgrd</application> 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>
|
||||||
|
[2019-03-15 06:37:50] [WARNING] unable to connect to upstream node "node1" (node ID: 1)
|
||||||
|
[2019-03-15 06:37:50] [INFO] checking state of node 1, 1 of 3 attempts
|
||||||
|
[2019-03-15 06:37:50] [INFO] sleeping 5 seconds until next reconnection attempt
|
||||||
|
[2019-03-15 06:37:55] [INFO] checking state of node 1, 2 of 3 attempts
|
||||||
|
[2019-03-15 06:37:55] [INFO] sleeping 5 seconds until next reconnection attempt
|
||||||
|
[2019-03-15 06:38:00] [INFO] checking state of node 1, 3 of 3 attempts
|
||||||
|
[2019-03-15 06:38:00] [WARNING] unable to reconnect to node 1 after 3 attempts
|
||||||
|
[2019-03-15 06:38:00] [INFO] primary and this node have the same location ("default")
|
||||||
|
[2019-03-15 06:38:00] [INFO] local node's last receive lsn: 0/900CBF8
|
||||||
|
[2019-03-15 06:38:00] [INFO] node 3 last saw primary node 12 second(s) ago
|
||||||
|
[2019-03-15 06:38:00] [INFO] last receive LSN for sibling node "node3" (ID: 3) is: 0/900CBF8
|
||||||
|
[2019-03-15 06:38:00] [INFO] node "node3" (ID: 3) has same LSN as current candidate "node2" (ID: 2)
|
||||||
|
[2019-03-15 06:38:00] [INFO] visible nodes: 2; total nodes: 2; no nodes have seen the primary within the last 4 seconds
|
||||||
|
[2019-03-15 06:38:00] [NOTICE] promotion candidate is "node2" (ID: 2)
|
||||||
|
[2019-03-15 06:38:00] [NOTICE] this node is the winner, will now promote itself and inform other nodes
|
||||||
|
[2019-03-15 06:38:00] [INFO] promote_command is:
|
||||||
|
"/usr/pgsql-11/bin/repmgr -f /etc/repmgr/11/repmgr.conf standby promote"
|
||||||
|
NOTICE: promoting standby to primary
|
||||||
|
DETAIL: promoting server "node2" (ID: 2) using "/usr/pgsql-11/bin/pg_ctl -w -D '/var/lib/pgsql/11/data' promote"
|
||||||
|
NOTICE: waiting up to 60 seconds (parameter "promote_check_timeout") for promotion to complete
|
||||||
|
NOTICE: STANDBY PROMOTE successful
|
||||||
|
DETAIL: server "node2" (ID: 2) was successfully promoted to primary
|
||||||
|
[2019-03-15 06:38:01] [INFO] 3 followers to notify
|
||||||
|
[2019-03-15 06:38:01] [NOTICE] notifying node "node3" (node ID: 3) to follow node 2
|
||||||
|
INFO: node 3 received notification to follow node 2
|
||||||
|
[2019-03-15 06:38:01] [INFO] switching to primary monitoring mode
|
||||||
|
[2019-03-15 06:38:01] [NOTICE] monitoring cluster primary "node2" (node ID: 2)</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 --compact
|
||||||
|
ID | Name | Role | Status | Upstream | Location | Prio.
|
||||||
|
----+-------+---------+-----------+----------+----------+-------
|
||||||
|
1 | node1 | primary | - failed | | default | 100
|
||||||
|
2 | node2 | primary | * running | | default | 100
|
||||||
|
3 | node3 | standby | running | node2 | default | 100</programlisting>
|
||||||
|
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
<link linkend="repmgr-cluster-event"><command>repmgr cluster event</command></link> 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 | 2019-03-15 06:38:03 | node 3 now following new upstream node 2
|
||||||
|
3 | node3 | standby_follow | t | 2019-03-15 06:38:02 | standby attached to upstream node "node2" (node ID: 2)
|
||||||
|
2 | node2 | repmgrd_reload | t | 2019-03-15 06:38:01 | monitoring cluster primary "node2" (node ID: 2)
|
||||||
|
2 | node2 | repmgrd_failover_promote | t | 2019-03-15 06:38:01 | node 2 promoted to primary; old primary 1 marked as failed
|
||||||
|
2 | node2 | standby_promote | t | 2019-03-15 06:38:01 | server "node2" (ID: 2) was successfully promoted to primary</programlisting>
|
||||||
|
</para>
|
||||||
|
|
||||||
|
</sect1>
|
||||||
|
</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>
|
||||||
427
doc/switchover.sgml
Normal file
427
doc/switchover.sgml
Normal file
@@ -0,0 +1,427 @@
|
|||||||
|
<chapter id="performing-switchover" xreflabel="Performing a switchover with repmgr">
|
||||||
|
|
||||||
|
<indexterm>
|
||||||
|
<primary>switchover</primary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<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 also performs actions on other servers (the demotion
|
||||||
|
candidate, and optionally any other servers which are to follow the new primary),
|
||||||
|
which means passwordless SSH access is required to those servers 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
|
||||||
|
<xref linkend="switchover-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 in the previous section, success of the switchover operation depends on
|
||||||
|
&repmgr; being able to shut down the current primary server quickly and cleanly.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Ensure that the promotion candidate has sufficient free walsenders available
|
||||||
|
(PostgreSQL configuration item <varname>max_wal_senders</varname>), and if replication
|
||||||
|
slots are in use, at least one free slot is available for the demotion candidate (
|
||||||
|
PostgreSQL configuration item <varname>max_replication_slots</varname>).
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Ensure that a passwordless SSH connection is possible from the promotion candidate
|
||||||
|
(standby) to the demotion candidate (current primary). If <literal>--siblings-follow</literal>
|
||||||
|
will be used, ensure that passwordless SSH connections are possible from the
|
||||||
|
promotion candidate to all nodes attached to the demotion candidate
|
||||||
|
(including the witness server, if in use).
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<note>
|
||||||
|
<simpara>
|
||||||
|
&repmgr; expects to find the &repmgr; binary in the same path on the remote
|
||||||
|
server as on the local server.
|
||||||
|
</simpara>
|
||||||
|
</note>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Double-check which commands will be used to stop/start/restart the current
|
||||||
|
primary; this can be done by e.g. executing <command><link linkend="repmgr-node-service">repmgr node service</link></command>
|
||||||
|
on the current primary:
|
||||||
|
<programlisting>
|
||||||
|
repmgr -f /etc/repmgr.conf node service --list-actions --action=stop
|
||||||
|
repmgr -f /etc/repmgr.conf node service --list-actions --action=start
|
||||||
|
repmgr -f /etc/repmgr.conf node service --list-actions --action=restart</programlisting>
|
||||||
|
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
These commands can be defined in <filename>repmgr.conf</filename> with
|
||||||
|
<option>service_start_command</option>, <option>service_stop_command</option>
|
||||||
|
and <option>service_restart_command</option>.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<important>
|
||||||
|
<para>
|
||||||
|
If &repmgr; is installed from a package. you should set these commands
|
||||||
|
to use the appropriate service commands defined by the package/operating
|
||||||
|
system as these will ensure PostgreSQL is stopped/started properly
|
||||||
|
taking into account configuration and log file locations etc.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
If the <option>service_*_command</option> options aren't defined, &repmgr; will
|
||||||
|
fall back to using <application>pg_ctl</application> to stop/start/restart
|
||||||
|
PostgreSQL, which may not work properly, particularly when executed on a remote
|
||||||
|
server.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
For more details, see <xref linkend="configuration-file-service-commands">.
|
||||||
|
</para>
|
||||||
|
</important>
|
||||||
|
|
||||||
|
<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> is informed about the status of the PostgreSQL service.
|
||||||
|
</simpara>
|
||||||
|
<simpara>
|
||||||
|
If using <command>sudo</command> for the <command>systemctl</command> calls, make sure the
|
||||||
|
<command>sudo</command> specification doesn't require a real tty for the user. If not set
|
||||||
|
this way, <command>repmgr</command> will fail to stop the primary.
|
||||||
|
</simpara>
|
||||||
|
</note>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Check that access from applications is minimalized or preferably blocked
|
||||||
|
completely, so applications are not unexpectedly interrupted.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<note>
|
||||||
|
<para>
|
||||||
|
If an exclusive backup is running on the current primary, or if WAL replay is paused on the standby,
|
||||||
|
&repmgr; will <emphasis>not</emphasis> perform the switchover.
|
||||||
|
</para>
|
||||||
|
</note>
|
||||||
|
|
||||||
|
<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 of 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>
|
||||||
|
|
||||||
|
<note>
|
||||||
|
<para>
|
||||||
|
From <link linkend="release-4.2">repmgr 4.2</link>, &repmgr; will instruct any running
|
||||||
|
<application>repmgrd</application> instances to pause operations while the switchover
|
||||||
|
is being carried out, to prevent <application>repmgrd</application> from
|
||||||
|
unintentionally promoting a node. For more details, see <xref linkend="repmgrd-pausing">.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Users of &repmgr; versions prior to 4.2 should ensure that <application>repmgrd</application>
|
||||||
|
is not running on any nodes while a switchover is being executed.
|
||||||
|
</para>
|
||||||
|
</note>
|
||||||
|
|
||||||
|
|
||||||
|
<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 "node1" 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>
|
||||||
|
|
||||||
|
<important>
|
||||||
|
<para>
|
||||||
|
Be aware that <option>--dry-run</option> checks the prerequisites
|
||||||
|
for performing the switchover and some basic sanity checks on the
|
||||||
|
state of the database which might effect the switchover operation
|
||||||
|
(e.g. replication lag); it cannot however guarantee the switchover
|
||||||
|
operation will succeed. In particular, if the current primary
|
||||||
|
does not shut down cleanly, &repmgr; will not be able to reliably
|
||||||
|
execute the switchover (as there would be a danger of divergence
|
||||||
|
between the former and new primary nodes).
|
||||||
|
</para>
|
||||||
|
</important>
|
||||||
|
|
||||||
|
|
||||||
|
<note>
|
||||||
|
<simpara>
|
||||||
|
See <xref linkend="repmgr-standby-switchover"> for a full list of available
|
||||||
|
command line options and <filename>repmgr.conf</filename> settings relevant
|
||||||
|
to performing a switchover.
|
||||||
|
</simpara>
|
||||||
|
</note>
|
||||||
|
|
||||||
|
<sect2 id="switchover-pg-rewind" xreflabel="Switchover and pg_rewind">
|
||||||
|
<indexterm>
|
||||||
|
<primary>pg_rewind</primary>
|
||||||
|
<secondary>using with "repmgr standby switchover"</secondary>
|
||||||
|
</indexterm>
|
||||||
|
<title>Switchover and pg_rewind</title>
|
||||||
|
<para>
|
||||||
|
If the demotion candidate does not shut down smoothly or cleanly, there's a risk it
|
||||||
|
will have a slightly divergent timeline and will not be able to attach to the new
|
||||||
|
primary. To fix this situation without needing to reclone the old primary, it's
|
||||||
|
possible to use the <application>pg_rewind</application> utility, which will usually be
|
||||||
|
able to resync the two servers.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
To have &repmgr; execute <application>pg_rewind</application> if it detects this
|
||||||
|
situation after promoting the new primary, add the <option>--force-rewind</option>
|
||||||
|
option.
|
||||||
|
</para>
|
||||||
|
<note>
|
||||||
|
<simpara>
|
||||||
|
If &repmgr; detects a situation where it needs to execute <application>pg_rewind</application>,
|
||||||
|
it will execute a <literal>CHECKPOINT</literal> on the new primary before executing
|
||||||
|
<application>pg_rewind</application>.
|
||||||
|
</simpara>
|
||||||
|
</note>
|
||||||
|
<para>
|
||||||
|
For more details on <application>pg_rewind</application>, see:
|
||||||
|
<ulink url="https://www.postgresql.org/docs/current/app-pgrewind.html">https://www.postgresql.org/docs/current/app-pgrewind.html</ulink>.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
<application>pg_rewind</application> has been part of the core PostgreSQL distribution since
|
||||||
|
version 9.5. Users of versions 9.3 and 9.4 will need to manually install it; the source code is available here:
|
||||||
|
<ulink url="https://github.com/vmware/pg_rewind">https://github.com/vmware/pg_rewind</ulink>.
|
||||||
|
If the <application>pg_rewind</application>
|
||||||
|
binary is not installed in the PostgreSQL <filename>bin</filename> directory, provide
|
||||||
|
its full path on the demotion candidate with <option>--force-rewind</option>.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Note that building the 9.3/9.4 version of <application>pg_rewind</application> requires the PostgreSQL
|
||||||
|
source code. Also, PostgreSQL 9.3 does not provide <varname>wal_log_hints</varname>,
|
||||||
|
meaning data checksums must have been enabled when the database was initialized.
|
||||||
|
</para>
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
|
||||||
|
</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 "node1" 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>
|
||||||
|
<para>
|
||||||
|
If <application>repmgrd</application> is in use, it's worth double-checking that
|
||||||
|
all nodes are unpaused by executing <command><link linkend="repmgr-daemon-status">repmgr-daemon-status</link></command>.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<note>
|
||||||
|
<para>
|
||||||
|
Users of &repmgr; versions prior to 4.2 will need to manually restart <application>repmgrd</application>
|
||||||
|
on all nodes after the switchover is completed.
|
||||||
|
</para>
|
||||||
|
</note>
|
||||||
|
|
||||||
|
</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/app-pgrewind.html">pg_rewind documentation</ulink>
|
||||||
|
for details.
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
</para>
|
||||||
|
</sect1>
|
||||||
|
|
||||||
|
<sect1 id="switchover-troubleshooting" xreflabel="Troubleshooting">
|
||||||
|
<indexterm>
|
||||||
|
<primary>switchover</primary>
|
||||||
|
<secondary>troubleshooting</secondary>
|
||||||
|
</indexterm>
|
||||||
|
<title>Troubleshooting switchover issues</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
As <link linkend="performing-switchover">emphasised previously</link>, performing a switchover
|
||||||
|
is a non-trivial operation and there are a number of potential issues which can occur.
|
||||||
|
While &repmgr; attempts to perform sanity checks, there's no guaranteed way of determining the success of
|
||||||
|
a switchover without actually carrying it out.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<sect2 id="switchover-troubleshooting-primary-shutdown">
|
||||||
|
<title>Demotion candidate (old primary) does not shut down</title>
|
||||||
|
<para>
|
||||||
|
&repmgr; may abort a switchover with a message like:
|
||||||
|
<programlisting>
|
||||||
|
ERROR: shutdown of the primary server could not be confirmed
|
||||||
|
HINT: check the primary server status before performing any further actions</programlisting>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
This means the shutdown of the old primary has taken longer than &repmgr; expected,
|
||||||
|
and it has given up waiting.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
In this case, check the PostgreSQL log on the primary server to see what is going
|
||||||
|
on. It's entirely possible the shutdown process is just taking longer than the
|
||||||
|
timeout set by the configuration parameter <varname>shutdown_check_timeout</varname>
|
||||||
|
(default: 60 seconds), in which case you may need to adjust this parameter.
|
||||||
|
</para>
|
||||||
|
<note>
|
||||||
|
<para>
|
||||||
|
Note that <varname>shutdown_check_timeout</varname> is set on the node where
|
||||||
|
<command>repmgr standby switchover</command> is executed (promotion candidate); setting it on the
|
||||||
|
demotion candidate (former primary) will have no effect.
|
||||||
|
</para>
|
||||||
|
</note>
|
||||||
|
<para>
|
||||||
|
If the primary server has shut down cleanly, and no other node has been promoted,
|
||||||
|
it is safe to restart it, in which case the replication cluster will be restored
|
||||||
|
to its original configuration.
|
||||||
|
</para>
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
<sect2 id="switchover-troubleshooting-exclusive-backup">
|
||||||
|
<title>Switchover aborts with an "exclusive backup" error</title>
|
||||||
|
<para>
|
||||||
|
&repmgr; may abort a switchover with a message like:
|
||||||
|
<programlisting>
|
||||||
|
ERROR: unable to perform a switchover while primary server is in exclusive backup mode
|
||||||
|
HINT: stop backup before attempting the switchover</programlisting>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
This means an exclusive backup is running on the current primary; interrupting this
|
||||||
|
will not only abort the backup, but potentially leave the primary with an ambiguous
|
||||||
|
backup state.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
To proceed, either wait until the backup has finished, or cancel it with the command
|
||||||
|
<command>SELECT pg_stop_backup()</command>. For more details see the PostgreSQL
|
||||||
|
documentation section
|
||||||
|
<ulink url="https://www.postgresql.org/docs/current/continuous-archiving.html#BACKUP-LOWLEVEL-BASE-BACKUP-EXCLUSIVE">Making an exclusive low level backup</ulink>.
|
||||||
|
</para>
|
||||||
|
</sect2>
|
||||||
|
</sect1>
|
||||||
|
|
||||||
|
</chapter>
|
||||||
@@ -1,121 +1,9 @@
|
|||||||
Upgrading from repmgr 3
|
Upgrading from repmgr 3
|
||||||
=======================
|
=======================
|
||||||
|
|
||||||
The upgrade process consists of two steps:
|
This document has been integrated into the main `repmgr` documentation
|
||||||
|
and is now located here:
|
||||||
|
|
||||||
1) converting the repmgr.conf configuration files
|
> [Upgrading from repmgr 3.x](https://repmgr.org/docs/current/upgrading-from-repmgr-3.html)
|
||||||
2) upgrading the repmgr schema.
|
|
||||||
|
|
||||||
Scripts are provided to assist both with converting repmgr.conf
|
|
||||||
and upgrading the schema.
|
|
||||||
|
|
||||||
Converting repmgr.conf configuration files
|
|
||||||
------------------------------------------
|
|
||||||
|
|
||||||
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 `repmgr.nodes` (e.g. `node` → `node_id`), and
|
|
||||||
also for consistency with PostgreSQL naming conventions
|
|
||||||
(e.g. `loglevel` → `log_level`).
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
`repmgr` will issue a warning about deprecated/altered options.
|
|
||||||
|
|
||||||
|
|
||||||
### Changed parameters
|
|
||||||
|
|
||||||
Following parameters have been added:
|
|
||||||
|
|
||||||
- `data_directory`: this is mandatory and must contain the path
|
|
||||||
to the node's data directory
|
|
||||||
- `monitoring_history`: this replaces the `repmgrd` command line
|
|
||||||
option `--monitoring-history`
|
|
||||||
|
|
||||||
Following parameters have been renamed:
|
|
||||||
|
|
||||||
- `node` → `node_id`
|
|
||||||
- `loglevel` → `log_level`
|
|
||||||
- `logfacility` → `log_facility`
|
|
||||||
- `logfile` → `log_file`
|
|
||||||
- `master_reponse_timeout` → `async_query_timeout`
|
|
||||||
|
|
||||||
Following parameters have been removed:
|
|
||||||
|
|
||||||
- `cluster` is no longer required and will be ignored.
|
|
||||||
- `upstream_node_id` is replaced by the command-line parameter
|
|
||||||
`--upstream-node-id`
|
|
||||||
|
|
||||||
### Conversion script
|
|
||||||
|
|
||||||
To assist with conversion of `repmgr.conf` files, a Perl script
|
|
||||||
is provided in `contrib/convert-config.pl`. Use like this:
|
|
||||||
|
|
||||||
$ ./convert-config.pl /etc/repmgr.conf
|
|
||||||
node_id=2
|
|
||||||
node_name=node2
|
|
||||||
conninfo=host=localhost dbname=repmgr user=repmgr port=5602
|
|
||||||
pg_ctl_options='-l /tmp/postgres.5602.log'
|
|
||||||
pg_bindir=/home/barwick/devel/builds/HEAD/bin
|
|
||||||
rsync_options=--exclude=postgresql.local.conf --archive
|
|
||||||
log_level=DEBUG
|
|
||||||
pg_basebackup_options=--no-slot
|
|
||||||
data_directory=
|
|
||||||
|
|
||||||
The converted file is printed to `STDOUT` and the original file is not
|
|
||||||
changed.
|
|
||||||
|
|
||||||
Please note that the parameter `data_directory` *must* be provided;
|
|
||||||
if not already present, the conversion script will add an empty
|
|
||||||
placeholder parameter.
|
|
||||||
|
|
||||||
|
|
||||||
Upgrading the repmgr schema
|
|
||||||
---------------------------
|
|
||||||
|
|
||||||
Ensure `repmgrd` is not running, or any cron jobs which execute the
|
|
||||||
`repmgr` binary.
|
|
||||||
|
|
||||||
Install `repmgr4`; any `repmgr3` packages should be uninstalled
|
|
||||||
(if not automatically installed already).
|
|
||||||
|
|
||||||
### Manually create the repmgr extension
|
|
||||||
|
|
||||||
In the database used by the existing `repmgr` configuration, execute:
|
|
||||||
|
|
||||||
CREATE EXTENSION repmgr FROM unpackaged;
|
|
||||||
|
|
||||||
This will move and convert all objects from the existing schema
|
|
||||||
into the new, standard `repmgr` schema.
|
|
||||||
|
|
||||||
> *NOTE* there must be only one schema matching 'repmgr_%' in the
|
|
||||||
> database, otherwise this step may not work.
|
|
||||||
|
|
||||||
### Re-register each node
|
|
||||||
|
|
||||||
This is necessary to update the `repmgr` metadata with some additional items.
|
|
||||||
|
|
||||||
On the primary node, execute e.g.
|
|
||||||
|
|
||||||
repmgr primary register -f /etc/repmgr.conf --force
|
|
||||||
|
|
||||||
On each standby node, execute e.g.
|
|
||||||
|
|
||||||
repmgr standby register -f /etc/repmgr.conf --force
|
|
||||||
|
|
||||||
Check the data is updated as expected by examining the `repmgr.nodes` table;
|
|
||||||
restart `repmgrd` if required.
|
|
||||||
|
|
||||||
The original `repmgr_$cluster` schema can be dropped at any time.
|
|
||||||
|
|
||||||
* * *
|
|
||||||
|
|
||||||
> *TIP* If you don't care about any data from the existing `repmgr` installation,
|
|
||||||
> (e.g. the contents of the `events` and `monitoring` tables), the manual
|
|
||||||
> "CREATE EXTENSION" step can be skipped; just re-register each node, starting
|
|
||||||
> with the primary node, and the `repmgr` extension will be automatically created.
|
|
||||||
|
|
||||||
* * *
|
|
||||||
|
|||||||
521
doc/upgrading-repmgr.sgml
Normal file
521
doc/upgrading-repmgr.sgml
Normal file
@@ -0,0 +1,521 @@
|
|||||||
|
<chapter id="upgrading-repmgr" xreflabel="Upgrading repmgr">
|
||||||
|
|
||||||
|
<indexterm>
|
||||||
|
<primary>upgrading</primary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<title>Upgrading repmgr</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
&repmgr; is updated regularly with minor 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 major release (e.g. 4.0 to 4.1).
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<sect1 id="upgrading-repmgr-extension" xreflabel="Upgrading repmgr 4.x and later">
|
||||||
|
<indexterm>
|
||||||
|
<primary>upgrading</primary>
|
||||||
|
<secondary>repmgr 4.x and later</secondary>
|
||||||
|
</indexterm>
|
||||||
|
<title>Upgrading repmgr 4.x and later</title>
|
||||||
|
<para>
|
||||||
|
From version 4, &repmgr; consists of three elements:
|
||||||
|
<itemizedlist spacing="compact" mark="bullet">
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
the <application>repmgr</application> and <application>repmgrd</application> executables
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
the objects for the &repmgr; PostgreSQL extension (SQL files for creating/updating
|
||||||
|
repmgr metadata, and the extension control file)
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
the shared library module used by <application>repmgrd</application> which
|
||||||
|
is resident in the PostgreSQL backend
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
With <emphasis>minor releases</emphasis>, usually changes are only made to the <application>repmgr</application>
|
||||||
|
and <application>repmgrd</application> executables. In this case, the upgrade is quite straightforward,
|
||||||
|
and is simply a case of installing the new version, and restarting <application>repmgrd</application>
|
||||||
|
(if running).
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
For <emphasis>major releases</emphasis>, the &repmgr; PostgreSQL extension will need to be updated
|
||||||
|
to the latest version. Additionally, if the shared library module has been updated (this is sometimes,
|
||||||
|
but not always the case), PostgreSQL itself will need to be restarted on each node.
|
||||||
|
</para>
|
||||||
|
<important>
|
||||||
|
<para>
|
||||||
|
Always check the <link linkend="appendix-release-notes">release notes</link> for every
|
||||||
|
release as they may contain upgrade instructions particular to individual versions.
|
||||||
|
</para>
|
||||||
|
</important>
|
||||||
|
|
||||||
|
<sect2 id="upgrading-minor-version" xreflabel="Upgrading a minor version release">
|
||||||
|
<indexterm>
|
||||||
|
<primary>upgrading</primary>
|
||||||
|
<secondary>minor release</secondary>
|
||||||
|
</indexterm>
|
||||||
|
<title>Upgrading a minor version release</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
The process for installing minor version upgrades is quite straightforward:
|
||||||
|
|
||||||
|
<itemizedlist spacing="compact" mark="bullet">
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
install the new &repmgr; version
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
restart <application>repmgrd</application> on all nodes where it is running
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
</itemizedlist>
|
||||||
|
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<note>
|
||||||
|
<para>
|
||||||
|
Some packaging systems (e.g. <link linkend="packages-debian-ubuntu">Debian/Ubuntu</link>
|
||||||
|
may restart <application>repmgrd</application> as part of the package upgrade process.
|
||||||
|
</para>
|
||||||
|
</note>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Minor version upgrades can be performed in any order on the nodes in the replication
|
||||||
|
cluster.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
A PostgreSQL restart is <emphasis>not</emphasis> required for minor version upgrades.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<note>
|
||||||
|
<para>
|
||||||
|
The same &repmgr; "major version" (e.g. <literal>4.2</literal>) must be
|
||||||
|
installed on all nodes in the replication cluster. While it's possible to have differing
|
||||||
|
&repmgr; "minor versions" (e.g. <literal>4.2.1</literal>) on different nodes,
|
||||||
|
we strongly recommend updating all nodes to the latest minor version.
|
||||||
|
</para>
|
||||||
|
</note>
|
||||||
|
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
<sect2 id="upgrading-major-version" xreflabel="Upgrading a major version release">
|
||||||
|
<indexterm>
|
||||||
|
<primary>upgrading</primary>
|
||||||
|
<secondary>major release</secondary>
|
||||||
|
</indexterm>
|
||||||
|
<title>Upgrading a major version release</title>
|
||||||
|
<para>
|
||||||
|
"major version" upgrades need to be planned more carefully, as they may include
|
||||||
|
changes to the &repmgr; metadata (which need to be propagated from the primary to all
|
||||||
|
standbys) and/or changes to the shared object file used by <application>repmgrd</application>
|
||||||
|
(which require a PostgreSQL restart).
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
With this in mind,
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
<orderedlist>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
Stop <application>repmgrd</application> (if in use) on all nodes where it is running.
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
Disable the <application>repmgrd</application> service on all nodes where it is in use;
|
||||||
|
this is to prevent packages from prematurely restarting <application>repmgrd</application>.
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
Install the updated package (or compile the updated source) on all nodes.
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
If running a <literal>systemd</literal>-based Linux distribution, execute (as <literal>root</literal>,
|
||||||
|
or with appropriate <literal>sudo</literal> permissions):
|
||||||
|
<programlisting>
|
||||||
|
systemctl daemon-reload</programlisting>
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
If the &repmgr; shared library module has been updated (check the <link linkend="appendix-release-notes">release notes</link>!),
|
||||||
|
restart PostgreSQL, then <application>repmgrd</application> (if in use) on each node,
|
||||||
|
The order in which this is applied to individual nodes is not critical,
|
||||||
|
and it's also fine to restart PostgreSQL on all nodes first before starting <application>repmgrd</application>.
|
||||||
|
</simpara>
|
||||||
|
<simpara>
|
||||||
|
Note that if the upgrade requires a PostgreSQL restart, <application>repmgrd</application>
|
||||||
|
will only function correctly once all nodes have been restarted.
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
On the primary node, execute
|
||||||
|
<programlisting>
|
||||||
|
ALTER EXTENSION repmgr UPDATE</programlisting>
|
||||||
|
in the database where &repmgr; is installed.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
Reenable the <application>repmgrd</application> service on all nodes where it is in use, and
|
||||||
|
ensure it is running.
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
</orderedlist>
|
||||||
|
</para>
|
||||||
|
<tip>
|
||||||
|
<para>
|
||||||
|
If the &repmgr; upgrade requires a PostgreSQL restart, combine the &repmgr; upgrade
|
||||||
|
with a PostgreSQL minor version upgrade, which will require a restart in any case.
|
||||||
|
New PostgreSQL minor version are usually released every couple of months.
|
||||||
|
</para>
|
||||||
|
</tip>
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
<sect2 id="upgrading-check-repmgrd" xreflabel="Checking repmgrd status after an upgrade">
|
||||||
|
<indexterm>
|
||||||
|
<primary>upgrading</primary>
|
||||||
|
<secondary>checking repmgrd status</secondary>
|
||||||
|
</indexterm>
|
||||||
|
<title>Checking repmgrd status after an upgrade</title>
|
||||||
|
<para>
|
||||||
|
From <link linkend="release-4.2">repmgr 4.2</link>, once the upgrade is complete, execute the <command><link linkend="repmgr-daemon-status">repmgr daemon status</link></command>
|
||||||
|
command (on any node) to show an overview of the status of <application>repmgrd</application> on all nodes.
|
||||||
|
</para>
|
||||||
|
</sect2>
|
||||||
|
</sect1>
|
||||||
|
|
||||||
|
<sect1 id="upgrading-and-pg-upgrade" xreflabel="pg_upgrade and repmgr">
|
||||||
|
<indexterm>
|
||||||
|
<primary>upgrading</primary>
|
||||||
|
<secondary>pg_upgrade</secondary>
|
||||||
|
</indexterm>
|
||||||
|
<indexterm>
|
||||||
|
<primary>pg_upgrade</primary>
|
||||||
|
</indexterm>
|
||||||
|
<title>pg_upgrade and repmgr</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
<application>pg_upgrade</application> requires that if any functions are
|
||||||
|
dependent on a shared library, this library must be present in both
|
||||||
|
the old and new installations before <application>pg_upgrade</application>
|
||||||
|
can be executed.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
To minimize the risk of any upgrade issues (particularly if an upgrade to
|
||||||
|
a new major &repmgr; version is involved), we recommend upgrading
|
||||||
|
&repmgr; on the old server <emphasis>before</emphasis> running
|
||||||
|
<application>pg_upgrade</application> to ensure that old and new
|
||||||
|
versions are the same.
|
||||||
|
</para>
|
||||||
|
<note>
|
||||||
|
<simpara>
|
||||||
|
This issue applies to any PostgreSQL extension which has
|
||||||
|
dependencies on a shared library.
|
||||||
|
</simpara>
|
||||||
|
</note>
|
||||||
|
<para>
|
||||||
|
For further details please see the <ulink url="https://www.postgresql.org/docs/current/pgupgrade.html">pg_upgrade documentation</ulink>.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
If replication slots are in use, bear in mind these will <emphasis>not</emphasis>
|
||||||
|
be recreated by <application>pg_upgrade</application>. These will need to
|
||||||
|
be recreated manually.
|
||||||
|
</para>
|
||||||
|
<tip>
|
||||||
|
<para>
|
||||||
|
Use <command><link linkend="repmgr-node-check">repmgr node check</link></command>
|
||||||
|
to determine which replacation slots need to be recreated.
|
||||||
|
</para>
|
||||||
|
</tip>
|
||||||
|
|
||||||
|
</sect1>
|
||||||
|
|
||||||
|
|
||||||
|
<sect1 id="upgrading-from-repmgr-3" xreflabel="Upgrading from repmgr 3.x">
|
||||||
|
<indexterm>
|
||||||
|
<primary>upgrading</primary>
|
||||||
|
<secondary>from repmgr 3.x</secondary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<title>Upgrading from repmgr 3.x</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 using <command>CREATE EXTENSION</command>
|
||||||
|
</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>
|
||||||
|
<para>
|
||||||
|
The shared library has been renamed from <literal>repmgr_funcs</literal> to
|
||||||
|
<literal>repmgr</literal> - if it's set in <varname>shared_preload_libraries</varname>
|
||||||
|
in <filename>postgresql.conf</filename> it will need to be updated to the new name:
|
||||||
|
<programlisting>
|
||||||
|
shared_preload_libraries = 'repmgr'</programlisting>
|
||||||
|
</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 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
|
||||||
|
<application>repmgrd</application> 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>barman_server</varname></entry>
|
||||||
|
<entry><varname>barman_host</varname></entry>
|
||||||
|
</row>
|
||||||
|
<row>
|
||||||
|
<entry><varname>master_reponse_timeout</varname></entry>
|
||||||
|
<entry><varname>async_query_timeout</varname></entry>
|
||||||
|
</row>
|
||||||
|
</tbody>
|
||||||
|
</tgroup>
|
||||||
|
</table>
|
||||||
|
<note>
|
||||||
|
<para>
|
||||||
|
From &repmgr; 4, <literal>barman_server</literal> refers
|
||||||
|
to the server configured in Barman (in &repmgr; 3, the deprecated
|
||||||
|
<literal>cluster</literal> parameter was used for this);
|
||||||
|
the physical Barman hostname is configured with
|
||||||
|
<literal>barman_host</literal> (see <xref linkend="cloning-from-barman-prerequisites">
|
||||||
|
for details).
|
||||||
|
</para>
|
||||||
|
</note>
|
||||||
|
<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</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=node2 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 the conversion script will add an empty
|
||||||
|
placeholder parameter for <varname>data_directory</varname>, which
|
||||||
|
is a required parameter in repmgr4 and which <emphasis>must</emphasis>
|
||||||
|
be provided.
|
||||||
|
</para>
|
||||||
|
</sect3>
|
||||||
|
</sect2>
|
||||||
|
<sect2>
|
||||||
|
<title>Upgrading the repmgr schema</title>
|
||||||
|
<para>
|
||||||
|
Ensure <application>repmgrd</application> is not running, or any cron jobs which execute the
|
||||||
|
<command>repmgr</command> binary.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Install <literal>repmgr 4</literal> packages; any <literal>repmgr 3.x</literal> packages
|
||||||
|
should be uninstalled (if not automatically uninstalled already by your packaging system).
|
||||||
|
</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 <application>repmgrd</application> 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>
|
||||||
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,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* errcode.h
|
* errcode.h
|
||||||
* Copyright (c) 2ndQuadrant, 2010-2017
|
* Copyright (c) 2ndQuadrant, 2010-2019
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -43,5 +43,11 @@
|
|||||||
#define ERR_BARMAN 19
|
#define ERR_BARMAN 19
|
||||||
#define ERR_REGISTRATION_SYNC 20
|
#define ERR_REGISTRATION_SYNC 20
|
||||||
#define ERR_OUT_OF_MEMORY 21
|
#define ERR_OUT_OF_MEMORY 21
|
||||||
|
#define ERR_SWITCHOVER_INCOMPLETE 22
|
||||||
|
#define ERR_FOLLOW_FAIL 23
|
||||||
|
#define ERR_REJOIN_FAIL 24
|
||||||
|
#define ERR_NODE_STATUS 25
|
||||||
|
#define ERR_REPMGRD_PAUSE 26
|
||||||
|
#define ERR_REPMGRD_SERVICE 27
|
||||||
|
|
||||||
#endif /* _ERRCODE_H_ */
|
#endif /* _ERRCODE_H_ */
|
||||||
|
|||||||
@@ -38,16 +38,16 @@ SELECT repmgr.am_bdr_failover_handler(-1);
|
|||||||
|
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
|
SELECT repmgr.am_bdr_failover_handler(NULL);
|
||||||
|
am_bdr_failover_handler
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
SELECT repmgr.get_new_primary();
|
SELECT repmgr.get_new_primary();
|
||||||
get_new_primary
|
get_new_primary
|
||||||
-----------------
|
-----------------
|
||||||
|
-1
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SELECT repmgr.get_voting_status();
|
|
||||||
get_voting_status
|
|
||||||
-------------------
|
|
||||||
|
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
SELECT repmgr.notify_follow_primary(-1);
|
SELECT repmgr.notify_follow_primary(-1);
|
||||||
@@ -56,15 +56,9 @@ SELECT repmgr.notify_follow_primary(-1);
|
|||||||
|
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
SELECT repmgr.other_node_is_candidate(-1,-1);
|
SELECT repmgr.notify_follow_primary(NULL);
|
||||||
other_node_is_candidate
|
notify_follow_primary
|
||||||
-------------------------
|
-----------------------
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SELECT repmgr.request_vote(-1,-1);
|
|
||||||
request_vote
|
|
||||||
--------------
|
|
||||||
|
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
@@ -80,10 +74,10 @@ SELECT repmgr.set_local_node_id(-1);
|
|||||||
|
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
SELECT repmgr.set_voting_status_initiated();
|
SELECT repmgr.set_local_node_id(NULL);
|
||||||
set_voting_status_initiated
|
set_local_node_id
|
||||||
-----------------------------
|
-------------------
|
||||||
|
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
SELECT repmgr.standby_get_last_updated();
|
SELECT repmgr.standby_get_last_updated();
|
||||||
|
|||||||
23
log.c
23
log.c
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* log.c - Logging methods
|
* log.c - Logging methods
|
||||||
* Copyright (c) 2ndQuadrant, 2010-2017
|
* Copyright (c) 2ndQuadrant, 2010-2019
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -42,7 +42,7 @@ _stderr_log_with_level(const char *level_name, int level, const char *fmt, va_li
|
|||||||
__attribute__((format(PG_PRINTF_ATTRIBUTE, 3, 0)));
|
__attribute__((format(PG_PRINTF_ATTRIBUTE, 3, 0)));
|
||||||
|
|
||||||
int log_type = REPMGR_STDERR;
|
int log_type = REPMGR_STDERR;
|
||||||
int log_level = LOG_NOTICE;
|
int log_level = LOG_INFO;
|
||||||
int last_log_level = LOG_INFO;
|
int last_log_level = LOG_INFO;
|
||||||
int verbose_logging = false;
|
int verbose_logging = false;
|
||||||
int terse_logging = false;
|
int terse_logging = false;
|
||||||
@@ -70,7 +70,7 @@ _stderr_log_with_level(const char *level_name, int level, const char *fmt, va_li
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Store the requested level so that if there's a subsequent log_hint() or
|
* Store the requested level so that if there's a subsequent log_hint() or
|
||||||
* log_detail(), we can suppress that if appropriate.
|
* log_detail(), we can suppress that if --terse was specified,
|
||||||
*/
|
*/
|
||||||
last_log_level = level;
|
last_log_level = level;
|
||||||
|
|
||||||
@@ -85,7 +85,7 @@ _stderr_log_with_level(const char *level_name, int level, const char *fmt, va_li
|
|||||||
|
|
||||||
time(&t);
|
time(&t);
|
||||||
tm = localtime(&t);
|
tm = localtime(&t);
|
||||||
strftime(buf, 100, "[%Y-%m-%d %H:%M:%S]", tm);
|
strftime(buf, sizeof(buf), "[%Y-%m-%d %H:%M:%S]", tm);
|
||||||
fprintf(stderr, "%s [%s] ", buf, level_name);
|
fprintf(stderr, "%s [%s] ", buf, level_name);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -329,6 +329,21 @@ logger_set_terse(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
logger_set_level(int new_log_level)
|
||||||
|
{
|
||||||
|
log_level = new_log_level;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
logger_set_min_level(int min_log_level)
|
||||||
|
{
|
||||||
|
if (min_log_level > log_level)
|
||||||
|
log_level = min_log_level;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
detect_log_level(const char *level)
|
detect_log_level(const char *level)
|
||||||
{
|
{
|
||||||
|
|||||||
4
log.h
4
log.h
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* log.h
|
* log.h
|
||||||
* Copyright (c) 2ndQuadrant, 2010-2017
|
* Copyright (c) 2ndQuadrant, 2010-2019
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -128,6 +128,8 @@ bool logger_shutdown(void);
|
|||||||
|
|
||||||
void logger_set_verbose(void);
|
void logger_set_verbose(void);
|
||||||
void logger_set_terse(void);
|
void logger_set_terse(void);
|
||||||
|
void logger_set_min_level(int min_log_level);
|
||||||
|
void logger_set_level(int new_log_level);
|
||||||
|
|
||||||
void
|
void
|
||||||
log_detail(const char *fmt,...)
|
log_detail(const char *fmt,...)
|
||||||
|
|||||||
2
repmgr--4.0--4.1.sql
Normal file
2
repmgr--4.0--4.1.sql
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
-- complain if script is sourced in psql, rather than via CREATE EXTENSION
|
||||||
|
\echo Use "CREATE EXTENSION repmgr" to load this file. \quit
|
||||||
@@ -6,7 +6,7 @@ CREATE TABLE repmgr.nodes (
|
|||||||
upstream_node_id INTEGER NULL REFERENCES nodes (node_id) DEFERRABLE,
|
upstream_node_id INTEGER NULL REFERENCES nodes (node_id) DEFERRABLE,
|
||||||
active BOOLEAN NOT NULL DEFAULT TRUE,
|
active BOOLEAN NOT NULL DEFAULT TRUE,
|
||||||
node_name TEXT NOT NULL,
|
node_name TEXT NOT NULL,
|
||||||
type TEXT NOT NULL CHECK (type IN('primary','standby','bdr')),
|
type TEXT NOT NULL CHECK (type IN('primary','standby','witness','bdr')),
|
||||||
location TEXT NOT NULL DEFAULT 'default',
|
location TEXT NOT NULL DEFAULT 'default',
|
||||||
priority INT NOT NULL DEFAULT 100,
|
priority INT NOT NULL DEFAULT 100,
|
||||||
conninfo TEXT NOT NULL,
|
conninfo TEXT NOT NULL,
|
||||||
@@ -79,6 +79,19 @@ LEFT JOIN repmgr.nodes un
|
|||||||
ON un.node_id = n.upstream_node_id;
|
ON un.node_id = n.upstream_node_id;
|
||||||
|
|
||||||
|
|
||||||
|
/* XXX update upgrade scripts! */
|
||||||
|
CREATE TABLE repmgr.voting_term (
|
||||||
|
term INT NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX voting_term_restrict
|
||||||
|
ON repmgr.voting_term ((TRUE));
|
||||||
|
|
||||||
|
CREATE RULE voting_term_delete AS
|
||||||
|
ON DELETE TO repmgr.voting_term
|
||||||
|
DO INSTEAD NOTHING;
|
||||||
|
|
||||||
|
|
||||||
/* ================= */
|
/* ================= */
|
||||||
/* repmgrd functions */
|
/* repmgrd functions */
|
||||||
/* ================= */
|
/* ================= */
|
||||||
@@ -90,6 +103,11 @@ CREATE FUNCTION set_local_node_id(INT)
|
|||||||
AS 'MODULE_PATHNAME', 'set_local_node_id'
|
AS 'MODULE_PATHNAME', 'set_local_node_id'
|
||||||
LANGUAGE C STRICT;
|
LANGUAGE C STRICT;
|
||||||
|
|
||||||
|
CREATE FUNCTION get_local_node_id()
|
||||||
|
RETURNS INT
|
||||||
|
AS 'MODULE_PATHNAME', 'get_local_node_id'
|
||||||
|
LANGUAGE C STRICT;
|
||||||
|
|
||||||
CREATE FUNCTION standby_set_last_updated()
|
CREATE FUNCTION standby_set_last_updated()
|
||||||
RETURNS TIMESTAMP WITH TIME ZONE
|
RETURNS TIMESTAMP WITH TIME ZONE
|
||||||
AS 'MODULE_PATHNAME', 'standby_set_last_updated'
|
AS 'MODULE_PATHNAME', 'standby_set_last_updated'
|
||||||
@@ -102,49 +120,6 @@ CREATE FUNCTION standby_get_last_updated()
|
|||||||
|
|
||||||
/* failover functions */
|
/* failover functions */
|
||||||
|
|
||||||
|
|
||||||
DO $repmgr$
|
|
||||||
DECLARE
|
|
||||||
DECLARE server_version_num INT;
|
|
||||||
BEGIN
|
|
||||||
SELECT setting
|
|
||||||
FROM pg_catalog.pg_settings
|
|
||||||
WHERE name = 'server_version_num'
|
|
||||||
INTO server_version_num;
|
|
||||||
|
|
||||||
IF server_version_num >= 90400 THEN
|
|
||||||
EXECUTE $repmgr_func$
|
|
||||||
CREATE FUNCTION request_vote(INT,INT)
|
|
||||||
RETURNS pg_lsn
|
|
||||||
AS 'MODULE_PATHNAME', 'request_vote'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
$repmgr_func$;
|
|
||||||
ELSE
|
|
||||||
EXECUTE $repmgr_func$
|
|
||||||
CREATE FUNCTION request_vote(INT,INT)
|
|
||||||
RETURNS TEXT
|
|
||||||
AS 'MODULE_PATHNAME', 'request_vote'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
$repmgr_func$;
|
|
||||||
END IF;
|
|
||||||
END$repmgr$;
|
|
||||||
|
|
||||||
|
|
||||||
CREATE FUNCTION get_voting_status()
|
|
||||||
RETURNS INT
|
|
||||||
AS 'MODULE_PATHNAME', 'get_voting_status'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE FUNCTION set_voting_status_initiated()
|
|
||||||
RETURNS INT
|
|
||||||
AS 'MODULE_PATHNAME', 'set_voting_status_initiated'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE FUNCTION other_node_is_candidate(INT, INT)
|
|
||||||
RETURNS BOOL
|
|
||||||
AS 'MODULE_PATHNAME', 'other_node_is_candidate'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE FUNCTION notify_follow_primary(INT)
|
CREATE FUNCTION notify_follow_primary(INT)
|
||||||
RETURNS VOID
|
RETURNS VOID
|
||||||
AS 'MODULE_PATHNAME', 'notify_follow_primary'
|
AS 'MODULE_PATHNAME', 'notify_follow_primary'
|
||||||
@@ -160,13 +135,11 @@ CREATE FUNCTION reset_voting_status()
|
|||||||
AS 'MODULE_PATHNAME', 'reset_voting_status'
|
AS 'MODULE_PATHNAME', 'reset_voting_status'
|
||||||
LANGUAGE C STRICT;
|
LANGUAGE C STRICT;
|
||||||
|
|
||||||
|
|
||||||
CREATE FUNCTION am_bdr_failover_handler(INT)
|
CREATE FUNCTION am_bdr_failover_handler(INT)
|
||||||
RETURNS BOOL
|
RETURNS BOOL
|
||||||
AS 'MODULE_PATHNAME', 'am_bdr_failover_handler'
|
AS 'MODULE_PATHNAME', 'am_bdr_failover_handler'
|
||||||
LANGUAGE C STRICT;
|
LANGUAGE C STRICT;
|
||||||
|
|
||||||
|
|
||||||
CREATE FUNCTION unset_bdr_failover_handler()
|
CREATE FUNCTION unset_bdr_failover_handler()
|
||||||
RETURNS VOID
|
RETURNS VOID
|
||||||
AS 'MODULE_PATHNAME', 'unset_bdr_failover_handler'
|
AS 'MODULE_PATHNAME', 'unset_bdr_failover_handler'
|
||||||
|
|||||||
32
repmgr--4.1--4.2.sql
Normal file
32
repmgr--4.1--4.2.sql
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
-- complain if script is sourced in psql, rather than via CREATE EXTENSION
|
||||||
|
\echo Use "CREATE EXTENSION repmgr" to load this file. \quit
|
||||||
|
|
||||||
|
CREATE FUNCTION get_repmgrd_pid()
|
||||||
|
RETURNS INT
|
||||||
|
AS 'MODULE_PATHNAME', 'get_repmgrd_pid'
|
||||||
|
LANGUAGE C STRICT;
|
||||||
|
|
||||||
|
CREATE FUNCTION get_repmgrd_pidfile()
|
||||||
|
RETURNS TEXT
|
||||||
|
AS 'MODULE_PATHNAME', 'get_repmgrd_pidfile'
|
||||||
|
LANGUAGE C STRICT;
|
||||||
|
|
||||||
|
CREATE FUNCTION set_repmgrd_pid(INT, TEXT)
|
||||||
|
RETURNS VOID
|
||||||
|
AS 'MODULE_PATHNAME', 'set_repmgrd_pid'
|
||||||
|
LANGUAGE C STRICT;
|
||||||
|
|
||||||
|
CREATE FUNCTION repmgrd_is_running()
|
||||||
|
RETURNS BOOL
|
||||||
|
AS 'MODULE_PATHNAME', 'repmgrd_is_running'
|
||||||
|
LANGUAGE C STRICT;
|
||||||
|
|
||||||
|
CREATE FUNCTION repmgrd_pause(BOOL)
|
||||||
|
RETURNS VOID
|
||||||
|
AS 'MODULE_PATHNAME', 'repmgrd_pause'
|
||||||
|
LANGUAGE C STRICT;
|
||||||
|
|
||||||
|
CREATE FUNCTION repmgrd_is_paused()
|
||||||
|
RETURNS BOOL
|
||||||
|
AS 'MODULE_PATHNAME', 'repmgrd_is_paused'
|
||||||
|
LANGUAGE C STRICT;
|
||||||
166
repmgr--4.1.sql
Normal file
166
repmgr--4.1.sql
Normal file
@@ -0,0 +1,166 @@
|
|||||||
|
-- complain if script is sourced in psql, rather than via CREATE EXTENSION
|
||||||
|
\echo Use "CREATE EXTENSION repmgr" to load this file. \quit
|
||||||
|
|
||||||
|
CREATE TABLE repmgr.nodes (
|
||||||
|
node_id INTEGER PRIMARY KEY,
|
||||||
|
upstream_node_id INTEGER NULL REFERENCES nodes (node_id) DEFERRABLE,
|
||||||
|
active BOOLEAN NOT NULL DEFAULT TRUE,
|
||||||
|
node_name TEXT NOT NULL,
|
||||||
|
type TEXT NOT NULL CHECK (type IN('primary','standby','witness','bdr')),
|
||||||
|
location TEXT NOT NULL DEFAULT 'default',
|
||||||
|
priority INT NOT NULL DEFAULT 100,
|
||||||
|
conninfo TEXT NOT NULL,
|
||||||
|
repluser VARCHAR(63) NOT NULL,
|
||||||
|
slot_name TEXT NULL,
|
||||||
|
config_file TEXT NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE repmgr.events (
|
||||||
|
node_id INTEGER NOT NULL,
|
||||||
|
event TEXT NOT NULL,
|
||||||
|
successful BOOLEAN NOT NULL DEFAULT TRUE,
|
||||||
|
event_timestamp TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
details TEXT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
DO $repmgr$
|
||||||
|
DECLARE
|
||||||
|
DECLARE server_version_num INT;
|
||||||
|
BEGIN
|
||||||
|
SELECT setting
|
||||||
|
FROM pg_catalog.pg_settings
|
||||||
|
WHERE name = 'server_version_num'
|
||||||
|
INTO server_version_num;
|
||||||
|
IF server_version_num >= 90400 THEN
|
||||||
|
EXECUTE $repmgr_func$
|
||||||
|
CREATE TABLE repmgr.monitoring_history (
|
||||||
|
primary_node_id INTEGER NOT NULL,
|
||||||
|
standby_node_id INTEGER NOT NULL,
|
||||||
|
last_monitor_time TIMESTAMP WITH TIME ZONE NOT NULL,
|
||||||
|
last_apply_time TIMESTAMP WITH TIME ZONE,
|
||||||
|
last_wal_primary_location PG_LSN NOT NULL,
|
||||||
|
last_wal_standby_location PG_LSN,
|
||||||
|
replication_lag BIGINT NOT NULL,
|
||||||
|
apply_lag BIGINT NOT NULL
|
||||||
|
)
|
||||||
|
$repmgr_func$;
|
||||||
|
ELSE
|
||||||
|
EXECUTE $repmgr_func$
|
||||||
|
CREATE TABLE repmgr.monitoring_history (
|
||||||
|
primary_node_id INTEGER NOT NULL,
|
||||||
|
standby_node_id INTEGER NOT NULL,
|
||||||
|
last_monitor_time TIMESTAMP WITH TIME ZONE NOT NULL,
|
||||||
|
last_apply_time TIMESTAMP WITH TIME ZONE,
|
||||||
|
last_wal_primary_location TEXT NOT NULL,
|
||||||
|
last_wal_standby_location TEXT,
|
||||||
|
replication_lag BIGINT NOT NULL,
|
||||||
|
apply_lag BIGINT NOT NULL
|
||||||
|
)
|
||||||
|
$repmgr_func$;
|
||||||
|
END IF;
|
||||||
|
END$repmgr$;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
CREATE INDEX idx_monitoring_history_time
|
||||||
|
ON repmgr.monitoring_history (last_monitor_time, standby_node_id);
|
||||||
|
|
||||||
|
CREATE VIEW repmgr.show_nodes AS
|
||||||
|
SELECT n.node_id,
|
||||||
|
n.node_name,
|
||||||
|
n.active,
|
||||||
|
n.upstream_node_id,
|
||||||
|
un.node_name AS upstream_node_name,
|
||||||
|
n.type,
|
||||||
|
n.priority,
|
||||||
|
n.conninfo
|
||||||
|
FROM repmgr.nodes n
|
||||||
|
LEFT JOIN repmgr.nodes un
|
||||||
|
ON un.node_id = n.upstream_node_id;
|
||||||
|
|
||||||
|
|
||||||
|
/* XXX update upgrade scripts! */
|
||||||
|
CREATE TABLE repmgr.voting_term (
|
||||||
|
term INT NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX voting_term_restrict
|
||||||
|
ON repmgr.voting_term ((TRUE));
|
||||||
|
|
||||||
|
CREATE RULE voting_term_delete AS
|
||||||
|
ON DELETE TO repmgr.voting_term
|
||||||
|
DO INSTEAD NOTHING;
|
||||||
|
|
||||||
|
|
||||||
|
/* ================= */
|
||||||
|
/* repmgrd functions */
|
||||||
|
/* ================= */
|
||||||
|
|
||||||
|
/* monitoring functions */
|
||||||
|
|
||||||
|
CREATE FUNCTION set_local_node_id(INT)
|
||||||
|
RETURNS VOID
|
||||||
|
AS 'MODULE_PATHNAME', 'set_local_node_id'
|
||||||
|
LANGUAGE C STRICT;
|
||||||
|
|
||||||
|
CREATE FUNCTION get_local_node_id()
|
||||||
|
RETURNS INT
|
||||||
|
AS 'MODULE_PATHNAME', 'get_local_node_id'
|
||||||
|
LANGUAGE C STRICT;
|
||||||
|
|
||||||
|
CREATE FUNCTION standby_set_last_updated()
|
||||||
|
RETURNS TIMESTAMP WITH TIME ZONE
|
||||||
|
AS 'MODULE_PATHNAME', 'standby_set_last_updated'
|
||||||
|
LANGUAGE C STRICT;
|
||||||
|
|
||||||
|
CREATE FUNCTION standby_get_last_updated()
|
||||||
|
RETURNS TIMESTAMP WITH TIME ZONE
|
||||||
|
AS 'MODULE_PATHNAME', 'standby_get_last_updated'
|
||||||
|
LANGUAGE C STRICT;
|
||||||
|
|
||||||
|
/* failover functions */
|
||||||
|
|
||||||
|
CREATE FUNCTION notify_follow_primary(INT)
|
||||||
|
RETURNS VOID
|
||||||
|
AS 'MODULE_PATHNAME', 'notify_follow_primary'
|
||||||
|
LANGUAGE C STRICT;
|
||||||
|
|
||||||
|
CREATE FUNCTION get_new_primary()
|
||||||
|
RETURNS INT
|
||||||
|
AS 'MODULE_PATHNAME', 'get_new_primary'
|
||||||
|
LANGUAGE C STRICT;
|
||||||
|
|
||||||
|
CREATE FUNCTION reset_voting_status()
|
||||||
|
RETURNS VOID
|
||||||
|
AS 'MODULE_PATHNAME', 'reset_voting_status'
|
||||||
|
LANGUAGE C STRICT;
|
||||||
|
|
||||||
|
CREATE FUNCTION am_bdr_failover_handler(INT)
|
||||||
|
RETURNS BOOL
|
||||||
|
AS 'MODULE_PATHNAME', 'am_bdr_failover_handler'
|
||||||
|
LANGUAGE C STRICT;
|
||||||
|
|
||||||
|
CREATE FUNCTION unset_bdr_failover_handler()
|
||||||
|
RETURNS VOID
|
||||||
|
AS 'MODULE_PATHNAME', 'unset_bdr_failover_handler'
|
||||||
|
LANGUAGE C STRICT;
|
||||||
|
|
||||||
|
CREATE VIEW repmgr.replication_status AS
|
||||||
|
SELECT m.primary_node_id, m.standby_node_id, n.node_name AS standby_name,
|
||||||
|
n.type AS node_type, n.active, last_monitor_time,
|
||||||
|
CASE WHEN n.type='standby' THEN m.last_wal_primary_location ELSE NULL END AS last_wal_primary_location,
|
||||||
|
m.last_wal_standby_location,
|
||||||
|
CASE WHEN n.type='standby' THEN pg_catalog.pg_size_pretty(m.replication_lag) ELSE NULL END AS replication_lag,
|
||||||
|
CASE WHEN n.type='standby' THEN
|
||||||
|
CASE WHEN replication_lag > 0 THEN age(now(), m.last_apply_time) ELSE '0'::INTERVAL END
|
||||||
|
ELSE NULL
|
||||||
|
END AS replication_time_lag,
|
||||||
|
CASE WHEN n.type='standby' THEN pg_catalog.pg_size_pretty(m.apply_lag) ELSE NULL END AS apply_lag,
|
||||||
|
AGE(NOW(), CASE WHEN pg_catalog.pg_is_in_recovery() THEN repmgr.standby_get_last_updated() ELSE m.last_monitor_time END) AS communication_time_lag
|
||||||
|
FROM repmgr.monitoring_history m
|
||||||
|
JOIN repmgr.nodes n ON m.standby_node_id = n.node_id
|
||||||
|
WHERE (m.standby_node_id, m.last_monitor_time) IN (
|
||||||
|
SELECT m1.standby_node_id, MAX(m1.last_monitor_time)
|
||||||
|
FROM repmgr.monitoring_history m1 GROUP BY 1
|
||||||
|
);
|
||||||
|
|
||||||
17
repmgr--4.2--4.3.sql
Normal file
17
repmgr--4.2--4.3.sql
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
-- complain if script is sourced in psql, rather than via CREATE EXTENSION
|
||||||
|
\echo Use "CREATE EXTENSION repmgr" to load this file. \quit
|
||||||
|
|
||||||
|
CREATE FUNCTION set_upstream_last_seen()
|
||||||
|
RETURNS VOID
|
||||||
|
AS 'MODULE_PATHNAME', 'set_upstream_last_seen'
|
||||||
|
LANGUAGE C STRICT;
|
||||||
|
|
||||||
|
CREATE FUNCTION get_upstream_last_seen()
|
||||||
|
RETURNS INT
|
||||||
|
AS 'MODULE_PATHNAME', 'get_upstream_last_seen'
|
||||||
|
LANGUAGE C STRICT;
|
||||||
|
|
||||||
|
CREATE FUNCTION get_wal_receiver_pid()
|
||||||
|
RETURNS INT
|
||||||
|
AS 'MODULE_PATHNAME', 'get_wal_receiver_pid'
|
||||||
|
LANGUAGE C STRICT;
|
||||||
197
repmgr--4.2.sql
Normal file
197
repmgr--4.2.sql
Normal file
@@ -0,0 +1,197 @@
|
|||||||
|
-- complain if script is sourced in psql, rather than via CREATE EXTENSION
|
||||||
|
\echo Use "CREATE EXTENSION repmgr" to load this file. \quit
|
||||||
|
|
||||||
|
CREATE TABLE repmgr.nodes (
|
||||||
|
node_id INTEGER PRIMARY KEY,
|
||||||
|
upstream_node_id INTEGER NULL REFERENCES nodes (node_id) DEFERRABLE,
|
||||||
|
active BOOLEAN NOT NULL DEFAULT TRUE,
|
||||||
|
node_name TEXT NOT NULL,
|
||||||
|
type TEXT NOT NULL CHECK (type IN('primary','standby','witness','bdr')),
|
||||||
|
location TEXT NOT NULL DEFAULT 'default',
|
||||||
|
priority INT NOT NULL DEFAULT 100,
|
||||||
|
conninfo TEXT NOT NULL,
|
||||||
|
repluser VARCHAR(63) NOT NULL,
|
||||||
|
slot_name TEXT NULL,
|
||||||
|
config_file TEXT NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE repmgr.events (
|
||||||
|
node_id INTEGER NOT NULL,
|
||||||
|
event TEXT NOT NULL,
|
||||||
|
successful BOOLEAN NOT NULL DEFAULT TRUE,
|
||||||
|
event_timestamp TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
details TEXT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
DO $repmgr$
|
||||||
|
DECLARE
|
||||||
|
DECLARE server_version_num INT;
|
||||||
|
BEGIN
|
||||||
|
SELECT setting
|
||||||
|
FROM pg_catalog.pg_settings
|
||||||
|
WHERE name = 'server_version_num'
|
||||||
|
INTO server_version_num;
|
||||||
|
IF server_version_num >= 90400 THEN
|
||||||
|
EXECUTE $repmgr_func$
|
||||||
|
CREATE TABLE repmgr.monitoring_history (
|
||||||
|
primary_node_id INTEGER NOT NULL,
|
||||||
|
standby_node_id INTEGER NOT NULL,
|
||||||
|
last_monitor_time TIMESTAMP WITH TIME ZONE NOT NULL,
|
||||||
|
last_apply_time TIMESTAMP WITH TIME ZONE,
|
||||||
|
last_wal_primary_location PG_LSN NOT NULL,
|
||||||
|
last_wal_standby_location PG_LSN,
|
||||||
|
replication_lag BIGINT NOT NULL,
|
||||||
|
apply_lag BIGINT NOT NULL
|
||||||
|
)
|
||||||
|
$repmgr_func$;
|
||||||
|
ELSE
|
||||||
|
EXECUTE $repmgr_func$
|
||||||
|
CREATE TABLE repmgr.monitoring_history (
|
||||||
|
primary_node_id INTEGER NOT NULL,
|
||||||
|
standby_node_id INTEGER NOT NULL,
|
||||||
|
last_monitor_time TIMESTAMP WITH TIME ZONE NOT NULL,
|
||||||
|
last_apply_time TIMESTAMP WITH TIME ZONE,
|
||||||
|
last_wal_primary_location TEXT NOT NULL,
|
||||||
|
last_wal_standby_location TEXT,
|
||||||
|
replication_lag BIGINT NOT NULL,
|
||||||
|
apply_lag BIGINT NOT NULL
|
||||||
|
)
|
||||||
|
$repmgr_func$;
|
||||||
|
END IF;
|
||||||
|
END$repmgr$;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
CREATE INDEX idx_monitoring_history_time
|
||||||
|
ON repmgr.monitoring_history (last_monitor_time, standby_node_id);
|
||||||
|
|
||||||
|
CREATE VIEW repmgr.show_nodes AS
|
||||||
|
SELECT n.node_id,
|
||||||
|
n.node_name,
|
||||||
|
n.active,
|
||||||
|
n.upstream_node_id,
|
||||||
|
un.node_name AS upstream_node_name,
|
||||||
|
n.type,
|
||||||
|
n.priority,
|
||||||
|
n.conninfo
|
||||||
|
FROM repmgr.nodes n
|
||||||
|
LEFT JOIN repmgr.nodes un
|
||||||
|
ON un.node_id = n.upstream_node_id;
|
||||||
|
|
||||||
|
|
||||||
|
/* XXX update upgrade scripts! */
|
||||||
|
CREATE TABLE repmgr.voting_term (
|
||||||
|
term INT NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX voting_term_restrict
|
||||||
|
ON repmgr.voting_term ((TRUE));
|
||||||
|
|
||||||
|
CREATE RULE voting_term_delete AS
|
||||||
|
ON DELETE TO repmgr.voting_term
|
||||||
|
DO INSTEAD NOTHING;
|
||||||
|
|
||||||
|
|
||||||
|
/* ================= */
|
||||||
|
/* repmgrd functions */
|
||||||
|
/* ================= */
|
||||||
|
|
||||||
|
/* monitoring functions */
|
||||||
|
|
||||||
|
CREATE FUNCTION set_local_node_id(INT)
|
||||||
|
RETURNS VOID
|
||||||
|
AS 'MODULE_PATHNAME', 'set_local_node_id'
|
||||||
|
LANGUAGE C STRICT;
|
||||||
|
|
||||||
|
CREATE FUNCTION get_local_node_id()
|
||||||
|
RETURNS INT
|
||||||
|
AS 'MODULE_PATHNAME', 'get_local_node_id'
|
||||||
|
LANGUAGE C STRICT;
|
||||||
|
|
||||||
|
CREATE FUNCTION standby_set_last_updated()
|
||||||
|
RETURNS TIMESTAMP WITH TIME ZONE
|
||||||
|
AS 'MODULE_PATHNAME', 'standby_set_last_updated'
|
||||||
|
LANGUAGE C STRICT;
|
||||||
|
|
||||||
|
CREATE FUNCTION standby_get_last_updated()
|
||||||
|
RETURNS TIMESTAMP WITH TIME ZONE
|
||||||
|
AS 'MODULE_PATHNAME', 'standby_get_last_updated'
|
||||||
|
LANGUAGE C STRICT;
|
||||||
|
|
||||||
|
/* failover functions */
|
||||||
|
|
||||||
|
CREATE FUNCTION notify_follow_primary(INT)
|
||||||
|
RETURNS VOID
|
||||||
|
AS 'MODULE_PATHNAME', 'notify_follow_primary'
|
||||||
|
LANGUAGE C STRICT;
|
||||||
|
|
||||||
|
CREATE FUNCTION get_new_primary()
|
||||||
|
RETURNS INT
|
||||||
|
AS 'MODULE_PATHNAME', 'get_new_primary'
|
||||||
|
LANGUAGE C STRICT;
|
||||||
|
|
||||||
|
CREATE FUNCTION reset_voting_status()
|
||||||
|
RETURNS VOID
|
||||||
|
AS 'MODULE_PATHNAME', 'reset_voting_status'
|
||||||
|
LANGUAGE C STRICT;
|
||||||
|
|
||||||
|
CREATE FUNCTION am_bdr_failover_handler(INT)
|
||||||
|
RETURNS BOOL
|
||||||
|
AS 'MODULE_PATHNAME', 'am_bdr_failover_handler'
|
||||||
|
LANGUAGE C STRICT;
|
||||||
|
|
||||||
|
CREATE FUNCTION unset_bdr_failover_handler()
|
||||||
|
RETURNS VOID
|
||||||
|
AS 'MODULE_PATHNAME', 'unset_bdr_failover_handler'
|
||||||
|
LANGUAGE C STRICT;
|
||||||
|
|
||||||
|
CREATE FUNCTION get_repmgrd_pid()
|
||||||
|
RETURNS INT
|
||||||
|
AS 'MODULE_PATHNAME', 'get_repmgrd_pid'
|
||||||
|
LANGUAGE C STRICT;
|
||||||
|
|
||||||
|
CREATE FUNCTION get_repmgrd_pidfile()
|
||||||
|
RETURNS TEXT
|
||||||
|
AS 'MODULE_PATHNAME', 'get_repmgrd_pidfile'
|
||||||
|
LANGUAGE C STRICT;
|
||||||
|
|
||||||
|
CREATE FUNCTION set_repmgrd_pid(INT, TEXT)
|
||||||
|
RETURNS VOID
|
||||||
|
AS 'MODULE_PATHNAME', 'set_repmgrd_pid'
|
||||||
|
LANGUAGE C STRICT;
|
||||||
|
|
||||||
|
CREATE FUNCTION repmgrd_is_running()
|
||||||
|
RETURNS BOOL
|
||||||
|
AS 'MODULE_PATHNAME', 'repmgrd_is_running'
|
||||||
|
LANGUAGE C STRICT;
|
||||||
|
|
||||||
|
CREATE FUNCTION repmgrd_pause(BOOL)
|
||||||
|
RETURNS VOID
|
||||||
|
AS 'MODULE_PATHNAME', 'repmgrd_pause'
|
||||||
|
LANGUAGE C STRICT;
|
||||||
|
|
||||||
|
CREATE FUNCTION repmgrd_is_paused()
|
||||||
|
RETURNS BOOL
|
||||||
|
AS 'MODULE_PATHNAME', 'repmgrd_is_paused'
|
||||||
|
LANGUAGE C STRICT;
|
||||||
|
|
||||||
|
|
||||||
|
CREATE VIEW repmgr.replication_status AS
|
||||||
|
SELECT m.primary_node_id, m.standby_node_id, n.node_name AS standby_name,
|
||||||
|
n.type AS node_type, n.active, last_monitor_time,
|
||||||
|
CASE WHEN n.type='standby' THEN m.last_wal_primary_location ELSE NULL END AS last_wal_primary_location,
|
||||||
|
m.last_wal_standby_location,
|
||||||
|
CASE WHEN n.type='standby' THEN pg_catalog.pg_size_pretty(m.replication_lag) ELSE NULL END AS replication_lag,
|
||||||
|
CASE WHEN n.type='standby' THEN
|
||||||
|
CASE WHEN replication_lag > 0 THEN age(now(), m.last_apply_time) ELSE '0'::INTERVAL END
|
||||||
|
ELSE NULL
|
||||||
|
END AS replication_time_lag,
|
||||||
|
CASE WHEN n.type='standby' THEN pg_catalog.pg_size_pretty(m.apply_lag) ELSE NULL END AS apply_lag,
|
||||||
|
AGE(NOW(), CASE WHEN pg_catalog.pg_is_in_recovery() THEN repmgr.standby_get_last_updated() ELSE m.last_monitor_time END) AS communication_time_lag
|
||||||
|
FROM repmgr.monitoring_history m
|
||||||
|
JOIN repmgr.nodes n ON m.standby_node_id = n.node_id
|
||||||
|
WHERE (m.standby_node_id, m.last_monitor_time) IN (
|
||||||
|
SELECT m1.standby_node_id, MAX(m1.last_monitor_time)
|
||||||
|
FROM repmgr.monitoring_history m1 GROUP BY 1
|
||||||
|
);
|
||||||
|
|
||||||
217
repmgr--4.3.sql
Normal file
217
repmgr--4.3.sql
Normal file
@@ -0,0 +1,217 @@
|
|||||||
|
-- complain if script is sourced in psql, rather than via CREATE EXTENSION
|
||||||
|
\echo Use "CREATE EXTENSION repmgr" to load this file. \quit
|
||||||
|
|
||||||
|
CREATE TABLE repmgr.nodes (
|
||||||
|
node_id INTEGER PRIMARY KEY,
|
||||||
|
upstream_node_id INTEGER NULL REFERENCES nodes (node_id) DEFERRABLE,
|
||||||
|
active BOOLEAN NOT NULL DEFAULT TRUE,
|
||||||
|
node_name TEXT NOT NULL,
|
||||||
|
type TEXT NOT NULL CHECK (type IN('primary','standby','witness','bdr')),
|
||||||
|
location TEXT NOT NULL DEFAULT 'default',
|
||||||
|
priority INT NOT NULL DEFAULT 100,
|
||||||
|
conninfo TEXT NOT NULL,
|
||||||
|
repluser VARCHAR(63) NOT NULL,
|
||||||
|
slot_name TEXT NULL,
|
||||||
|
config_file TEXT NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE repmgr.events (
|
||||||
|
node_id INTEGER NOT NULL,
|
||||||
|
event TEXT NOT NULL,
|
||||||
|
successful BOOLEAN NOT NULL DEFAULT TRUE,
|
||||||
|
event_timestamp TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
details TEXT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
DO $repmgr$
|
||||||
|
DECLARE
|
||||||
|
DECLARE server_version_num INT;
|
||||||
|
BEGIN
|
||||||
|
SELECT setting
|
||||||
|
FROM pg_catalog.pg_settings
|
||||||
|
WHERE name = 'server_version_num'
|
||||||
|
INTO server_version_num;
|
||||||
|
IF server_version_num >= 90400 THEN
|
||||||
|
EXECUTE $repmgr_func$
|
||||||
|
CREATE TABLE repmgr.monitoring_history (
|
||||||
|
primary_node_id INTEGER NOT NULL,
|
||||||
|
standby_node_id INTEGER NOT NULL,
|
||||||
|
last_monitor_time TIMESTAMP WITH TIME ZONE NOT NULL,
|
||||||
|
last_apply_time TIMESTAMP WITH TIME ZONE,
|
||||||
|
last_wal_primary_location PG_LSN NOT NULL,
|
||||||
|
last_wal_standby_location PG_LSN,
|
||||||
|
replication_lag BIGINT NOT NULL,
|
||||||
|
apply_lag BIGINT NOT NULL
|
||||||
|
)
|
||||||
|
$repmgr_func$;
|
||||||
|
ELSE
|
||||||
|
EXECUTE $repmgr_func$
|
||||||
|
CREATE TABLE repmgr.monitoring_history (
|
||||||
|
primary_node_id INTEGER NOT NULL,
|
||||||
|
standby_node_id INTEGER NOT NULL,
|
||||||
|
last_monitor_time TIMESTAMP WITH TIME ZONE NOT NULL,
|
||||||
|
last_apply_time TIMESTAMP WITH TIME ZONE,
|
||||||
|
last_wal_primary_location TEXT NOT NULL,
|
||||||
|
last_wal_standby_location TEXT,
|
||||||
|
replication_lag BIGINT NOT NULL,
|
||||||
|
apply_lag BIGINT NOT NULL
|
||||||
|
)
|
||||||
|
$repmgr_func$;
|
||||||
|
END IF;
|
||||||
|
END$repmgr$;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
CREATE INDEX idx_monitoring_history_time
|
||||||
|
ON repmgr.monitoring_history (last_monitor_time, standby_node_id);
|
||||||
|
|
||||||
|
CREATE VIEW repmgr.show_nodes AS
|
||||||
|
SELECT n.node_id,
|
||||||
|
n.node_name,
|
||||||
|
n.active,
|
||||||
|
n.upstream_node_id,
|
||||||
|
un.node_name AS upstream_node_name,
|
||||||
|
n.type,
|
||||||
|
n.priority,
|
||||||
|
n.conninfo
|
||||||
|
FROM repmgr.nodes n
|
||||||
|
LEFT JOIN repmgr.nodes un
|
||||||
|
ON un.node_id = n.upstream_node_id;
|
||||||
|
|
||||||
|
|
||||||
|
/* XXX update upgrade scripts! */
|
||||||
|
CREATE TABLE repmgr.voting_term (
|
||||||
|
term INT NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX voting_term_restrict
|
||||||
|
ON repmgr.voting_term ((TRUE));
|
||||||
|
|
||||||
|
CREATE RULE voting_term_delete AS
|
||||||
|
ON DELETE TO repmgr.voting_term
|
||||||
|
DO INSTEAD NOTHING;
|
||||||
|
|
||||||
|
|
||||||
|
/* ================= */
|
||||||
|
/* repmgrd functions */
|
||||||
|
/* ================= */
|
||||||
|
|
||||||
|
/* monitoring functions */
|
||||||
|
|
||||||
|
CREATE FUNCTION set_local_node_id(INT)
|
||||||
|
RETURNS VOID
|
||||||
|
AS 'MODULE_PATHNAME', 'set_local_node_id'
|
||||||
|
LANGUAGE C STRICT;
|
||||||
|
|
||||||
|
CREATE FUNCTION get_local_node_id()
|
||||||
|
RETURNS INT
|
||||||
|
AS 'MODULE_PATHNAME', 'get_local_node_id'
|
||||||
|
LANGUAGE C STRICT;
|
||||||
|
|
||||||
|
CREATE FUNCTION standby_set_last_updated()
|
||||||
|
RETURNS TIMESTAMP WITH TIME ZONE
|
||||||
|
AS 'MODULE_PATHNAME', 'standby_set_last_updated'
|
||||||
|
LANGUAGE C STRICT;
|
||||||
|
|
||||||
|
CREATE FUNCTION standby_get_last_updated()
|
||||||
|
RETURNS TIMESTAMP WITH TIME ZONE
|
||||||
|
AS 'MODULE_PATHNAME', 'standby_get_last_updated'
|
||||||
|
LANGUAGE C STRICT;
|
||||||
|
|
||||||
|
CREATE FUNCTION set_upstream_last_seen()
|
||||||
|
RETURNS VOID
|
||||||
|
AS 'MODULE_PATHNAME', 'set_upstream_last_seen'
|
||||||
|
LANGUAGE C STRICT;
|
||||||
|
|
||||||
|
CREATE FUNCTION get_upstream_last_seen()
|
||||||
|
RETURNS INT
|
||||||
|
AS 'MODULE_PATHNAME', 'get_upstream_last_seen'
|
||||||
|
LANGUAGE C STRICT;
|
||||||
|
|
||||||
|
|
||||||
|
/* failover functions */
|
||||||
|
|
||||||
|
CREATE FUNCTION notify_follow_primary(INT)
|
||||||
|
RETURNS VOID
|
||||||
|
AS 'MODULE_PATHNAME', 'notify_follow_primary'
|
||||||
|
LANGUAGE C STRICT;
|
||||||
|
|
||||||
|
CREATE FUNCTION get_new_primary()
|
||||||
|
RETURNS INT
|
||||||
|
AS 'MODULE_PATHNAME', 'get_new_primary'
|
||||||
|
LANGUAGE C STRICT;
|
||||||
|
|
||||||
|
CREATE FUNCTION reset_voting_status()
|
||||||
|
RETURNS VOID
|
||||||
|
AS 'MODULE_PATHNAME', 'reset_voting_status'
|
||||||
|
LANGUAGE C STRICT;
|
||||||
|
|
||||||
|
CREATE FUNCTION am_bdr_failover_handler(INT)
|
||||||
|
RETURNS BOOL
|
||||||
|
AS 'MODULE_PATHNAME', 'am_bdr_failover_handler'
|
||||||
|
LANGUAGE C STRICT;
|
||||||
|
|
||||||
|
CREATE FUNCTION unset_bdr_failover_handler()
|
||||||
|
RETURNS VOID
|
||||||
|
AS 'MODULE_PATHNAME', 'unset_bdr_failover_handler'
|
||||||
|
LANGUAGE C STRICT;
|
||||||
|
|
||||||
|
CREATE FUNCTION get_repmgrd_pid()
|
||||||
|
RETURNS INT
|
||||||
|
AS 'MODULE_PATHNAME', 'get_repmgrd_pid'
|
||||||
|
LANGUAGE C STRICT;
|
||||||
|
|
||||||
|
CREATE FUNCTION get_repmgrd_pidfile()
|
||||||
|
RETURNS TEXT
|
||||||
|
AS 'MODULE_PATHNAME', 'get_repmgrd_pidfile'
|
||||||
|
LANGUAGE C STRICT;
|
||||||
|
|
||||||
|
CREATE FUNCTION set_repmgrd_pid(INT, TEXT)
|
||||||
|
RETURNS VOID
|
||||||
|
AS 'MODULE_PATHNAME', 'set_repmgrd_pid'
|
||||||
|
LANGUAGE C STRICT;
|
||||||
|
|
||||||
|
CREATE FUNCTION repmgrd_is_running()
|
||||||
|
RETURNS BOOL
|
||||||
|
AS 'MODULE_PATHNAME', 'repmgrd_is_running'
|
||||||
|
LANGUAGE C STRICT;
|
||||||
|
|
||||||
|
CREATE FUNCTION repmgrd_pause(BOOL)
|
||||||
|
RETURNS VOID
|
||||||
|
AS 'MODULE_PATHNAME', 'repmgrd_pause'
|
||||||
|
LANGUAGE C STRICT;
|
||||||
|
|
||||||
|
CREATE FUNCTION repmgrd_is_paused()
|
||||||
|
RETURNS BOOL
|
||||||
|
AS 'MODULE_PATHNAME', 'repmgrd_is_paused'
|
||||||
|
LANGUAGE C STRICT;
|
||||||
|
|
||||||
|
CREATE FUNCTION get_wal_receiver_pid()
|
||||||
|
RETURNS INT
|
||||||
|
AS 'MODULE_PATHNAME', 'get_wal_receiver_pid'
|
||||||
|
LANGUAGE C STRICT;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* views */
|
||||||
|
|
||||||
|
CREATE VIEW repmgr.replication_status AS
|
||||||
|
SELECT m.primary_node_id, m.standby_node_id, n.node_name AS standby_name,
|
||||||
|
n.type AS node_type, n.active, last_monitor_time,
|
||||||
|
CASE WHEN n.type='standby' THEN m.last_wal_primary_location ELSE NULL END AS last_wal_primary_location,
|
||||||
|
m.last_wal_standby_location,
|
||||||
|
CASE WHEN n.type='standby' THEN pg_catalog.pg_size_pretty(m.replication_lag) ELSE NULL END AS replication_lag,
|
||||||
|
CASE WHEN n.type='standby' THEN
|
||||||
|
CASE WHEN replication_lag > 0 THEN age(now(), m.last_apply_time) ELSE '0'::INTERVAL END
|
||||||
|
ELSE NULL
|
||||||
|
END AS replication_time_lag,
|
||||||
|
CASE WHEN n.type='standby' THEN pg_catalog.pg_size_pretty(m.apply_lag) ELSE NULL END AS apply_lag,
|
||||||
|
AGE(NOW(), CASE WHEN pg_catalog.pg_is_in_recovery() THEN repmgr.standby_get_last_updated() ELSE m.last_monitor_time END) AS communication_time_lag
|
||||||
|
FROM repmgr.monitoring_history m
|
||||||
|
JOIN repmgr.nodes n ON m.standby_node_id = n.node_id
|
||||||
|
WHERE (m.standby_node_id, m.last_monitor_time) IN (
|
||||||
|
SELECT m1.standby_node_id, MAX(m1.last_monitor_time)
|
||||||
|
FROM repmgr.monitoring_history m1 GROUP BY 1
|
||||||
|
);
|
||||||
|
|
||||||
@@ -32,7 +32,7 @@ CREATE TABLE repmgr.nodes (
|
|||||||
upstream_node_id INTEGER NULL REFERENCES repmgr.nodes (node_id) DEFERRABLE,
|
upstream_node_id INTEGER NULL REFERENCES repmgr.nodes (node_id) DEFERRABLE,
|
||||||
active BOOLEAN NOT NULL DEFAULT TRUE,
|
active BOOLEAN NOT NULL DEFAULT TRUE,
|
||||||
node_name TEXT NOT NULL,
|
node_name TEXT NOT NULL,
|
||||||
type TEXT NOT NULL CHECK (type IN('primary','standby','bdr')),
|
type TEXT NOT NULL CHECK (type IN('primary','standby','witness','bdr')),
|
||||||
location TEXT NOT NULL DEFAULT 'default',
|
location TEXT NOT NULL DEFAULT 'default',
|
||||||
priority INT NOT NULL DEFAULT 100,
|
priority INT NOT NULL DEFAULT 100,
|
||||||
conninfo TEXT NOT NULL,
|
conninfo TEXT NOT NULL,
|
||||||
@@ -54,8 +54,34 @@ SELECT id, upstream_node_id, active, name,
|
|||||||
|
|
||||||
ALTER TABLE repmgr.repl_events RENAME TO events;
|
ALTER TABLE repmgr.repl_events RENAME TO events;
|
||||||
|
|
||||||
|
-- create new table "repmgr.voting_term"
|
||||||
|
CREATE TABLE repmgr.voting_term (
|
||||||
|
term INT NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX voting_term_restrict
|
||||||
|
ON repmgr.voting_term ((TRUE));
|
||||||
|
|
||||||
|
CREATE RULE voting_term_delete AS
|
||||||
|
ON DELETE TO repmgr.voting_term
|
||||||
|
DO INSTEAD NOTHING;
|
||||||
|
|
||||||
|
INSERT INTO repmgr.voting_term (term) VALUES (1);
|
||||||
|
|
||||||
|
|
||||||
-- convert "repmgr_$cluster.repl_monitor" to "monitoring_history"
|
-- convert "repmgr_$cluster.repl_monitor" to "monitoring_history"
|
||||||
|
|
||||||
|
|
||||||
|
DO $repmgr$
|
||||||
|
DECLARE
|
||||||
|
DECLARE server_version_num INT;
|
||||||
|
BEGIN
|
||||||
|
SELECT setting
|
||||||
|
FROM pg_catalog.pg_settings
|
||||||
|
WHERE name = 'server_version_num'
|
||||||
|
INTO server_version_num;
|
||||||
|
IF server_version_num >= 90400 THEN
|
||||||
|
EXECUTE $repmgr_func$
|
||||||
CREATE TABLE repmgr.monitoring_history (
|
CREATE TABLE repmgr.monitoring_history (
|
||||||
primary_node_id INTEGER NOT NULL,
|
primary_node_id INTEGER NOT NULL,
|
||||||
standby_node_id INTEGER NOT NULL,
|
standby_node_id INTEGER NOT NULL,
|
||||||
@@ -65,12 +91,32 @@ CREATE TABLE repmgr.monitoring_history (
|
|||||||
last_wal_standby_location PG_LSN,
|
last_wal_standby_location PG_LSN,
|
||||||
replication_lag BIGINT NOT NULL,
|
replication_lag BIGINT NOT NULL,
|
||||||
apply_lag BIGINT NOT NULL
|
apply_lag BIGINT NOT NULL
|
||||||
);
|
)
|
||||||
|
$repmgr_func$;
|
||||||
|
INSERT INTO repmgr.monitoring_history
|
||||||
|
(primary_node_id, standby_node_id, last_monitor_time, last_apply_time, last_wal_primary_location, last_wal_standby_location, replication_lag, apply_lag)
|
||||||
|
SELECT primary_node, standby_node, last_monitor_time, last_apply_time, last_wal_primary_location::pg_lsn, last_wal_standby_location::pg_lsn, replication_lag, apply_lag
|
||||||
|
FROM repmgr.repl_monitor;
|
||||||
|
ELSE
|
||||||
|
EXECUTE $repmgr_func$
|
||||||
|
CREATE TABLE repmgr.monitoring_history (
|
||||||
|
primary_node_id INTEGER NOT NULL,
|
||||||
|
standby_node_id INTEGER NOT NULL,
|
||||||
|
last_monitor_time TIMESTAMP WITH TIME ZONE NOT NULL,
|
||||||
|
last_apply_time TIMESTAMP WITH TIME ZONE,
|
||||||
|
last_wal_primary_location TEXT NOT NULL,
|
||||||
|
last_wal_standby_location TEXT,
|
||||||
|
replication_lag BIGINT NOT NULL,
|
||||||
|
apply_lag BIGINT NOT NULL
|
||||||
|
)
|
||||||
|
$repmgr_func$;
|
||||||
|
INSERT INTO repmgr.monitoring_history
|
||||||
|
(primary_node_id, standby_node_id, last_monitor_time, last_apply_time, last_wal_primary_location, last_wal_standby_location, replication_lag, apply_lag)
|
||||||
|
SELECT primary_node, standby_node, last_monitor_time, last_apply_time, last_wal_primary_location, last_wal_standby_location, replication_lag, apply_lag
|
||||||
|
FROM repmgr.repl_monitor;
|
||||||
|
|
||||||
INSERT INTO repmgr.monitoring_history
|
END IF;
|
||||||
(primary_node_id, standby_node_id, last_monitor_time, last_apply_time, last_wal_primary_location, last_wal_standby_location, replication_lag, apply_lag)
|
END$repmgr$;
|
||||||
SELECT primary_node, standby_node, last_monitor_time, last_apply_time, last_wal_primary_location::pg_lsn, last_wal_standby_location::pg_lsn, replication_lag, apply_lag
|
|
||||||
FROM repmgr.repl_monitor;
|
|
||||||
|
|
||||||
CREATE INDEX idx_monitoring_history_time
|
CREATE INDEX idx_monitoring_history_time
|
||||||
ON repmgr.monitoring_history (last_monitor_time, standby_node_id);
|
ON repmgr.monitoring_history (last_monitor_time, standby_node_id);
|
||||||
@@ -95,6 +141,16 @@ LEFT JOIN repmgr.nodes un
|
|||||||
|
|
||||||
/* monitoring functions */
|
/* monitoring functions */
|
||||||
|
|
||||||
|
CREATE FUNCTION set_local_node_id(INT)
|
||||||
|
RETURNS VOID
|
||||||
|
AS 'MODULE_PATHNAME', 'set_local_node_id'
|
||||||
|
LANGUAGE C STRICT;
|
||||||
|
|
||||||
|
CREATE FUNCTION get_local_node_id()
|
||||||
|
RETURNS INT
|
||||||
|
AS 'MODULE_PATHNAME', 'get_local_node_id'
|
||||||
|
LANGUAGE C STRICT;
|
||||||
|
|
||||||
CREATE FUNCTION standby_set_last_updated()
|
CREATE FUNCTION standby_set_last_updated()
|
||||||
RETURNS TIMESTAMP WITH TIME ZONE
|
RETURNS TIMESTAMP WITH TIME ZONE
|
||||||
AS '$libdir/repmgr', 'standby_set_last_updated'
|
AS '$libdir/repmgr', 'standby_set_last_updated'
|
||||||
@@ -108,26 +164,6 @@ CREATE FUNCTION standby_get_last_updated()
|
|||||||
|
|
||||||
/* failover functions */
|
/* failover functions */
|
||||||
|
|
||||||
CREATE FUNCTION request_vote(INT,INT)
|
|
||||||
RETURNS pg_lsn
|
|
||||||
AS '$libdir/repmgr', 'request_vote'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE FUNCTION get_voting_status()
|
|
||||||
RETURNS INT
|
|
||||||
AS '$libdir/repmgr', 'get_voting_status'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE FUNCTION set_voting_status_initiated()
|
|
||||||
RETURNS INT
|
|
||||||
AS '$libdir/repmgr', 'set_voting_status_initiated'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE FUNCTION other_node_is_candidate(INT, INT)
|
|
||||||
RETURNS BOOL
|
|
||||||
AS '$libdir/repmgr', 'other_node_is_candidate'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE FUNCTION notify_follow_primary(INT)
|
CREATE FUNCTION notify_follow_primary(INT)
|
||||||
RETURNS VOID
|
RETURNS VOID
|
||||||
AS '$libdir/repmgr', 'notify_follow_primary'
|
AS '$libdir/repmgr', 'notify_follow_primary'
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
/*
|
/*
|
||||||
* repmgr-action-standby.c
|
* repmgr-action-bdr.c
|
||||||
*
|
*
|
||||||
* Implements BDR-related actions for the repmgr command line utility
|
* Implements BDR-related actions for the repmgr command line utility
|
||||||
*
|
*
|
||||||
* Copyright (c) 2ndQuadrant, 2010-2017
|
* Copyright (c) 2ndQuadrant, 2010-2019
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -28,7 +28,7 @@
|
|||||||
/*
|
/*
|
||||||
* do_bdr_register()
|
* do_bdr_register()
|
||||||
*
|
*
|
||||||
* As each BDR node is its own master, registering a BDR node
|
* As each BDR node is its own primary, registering a BDR node
|
||||||
* will create the repmgr metadata schema if necessary.
|
* will create the repmgr metadata schema if necessary.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
@@ -83,17 +83,59 @@ do_bdr_register(void)
|
|||||||
exit(ERR_BAD_CONFIG);
|
exit(ERR_BAD_CONFIG);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bdr_nodes.node_count > 2)
|
/* BDR 2 implementation is for 2 nodes only */
|
||||||
|
if (get_bdr_version_num() < 3 && bdr_nodes.node_count > 2)
|
||||||
{
|
{
|
||||||
log_error(_("repmgr can only support BDR clusters with 2 nodes"));
|
log_error(_("repmgr can only support BDR 2.x clusters with 2 nodes"));
|
||||||
log_detail(_("this BDR cluster has %i nodes"), bdr_nodes.node_count);
|
log_detail(_("this BDR cluster has %i nodes"), bdr_nodes.node_count);
|
||||||
PQfinish(conn);
|
PQfinish(conn);
|
||||||
pfree(dbname);
|
pfree(dbname);
|
||||||
exit(ERR_BAD_CONFIG);
|
exit(ERR_BAD_CONFIG);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check whether repmgr extension exists, and that any other nodes are BDR */
|
if (get_bdr_version_num() > 2)
|
||||||
extension_status = get_repmgr_extension_status(conn);
|
{
|
||||||
|
log_error(_("\"repmgr bdr register\" is for BDR 2.x only"));
|
||||||
|
PQfinish(conn);
|
||||||
|
pfree(dbname);
|
||||||
|
exit(ERR_BAD_CONFIG);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* check for a matching BDR node */
|
||||||
|
{
|
||||||
|
PQExpBufferData bdr_local_node_name;
|
||||||
|
bool node_match = false;
|
||||||
|
|
||||||
|
initPQExpBuffer(&bdr_local_node_name);
|
||||||
|
node_match = bdr_node_name_matches(conn, config_file_options.node_name, &bdr_local_node_name);
|
||||||
|
|
||||||
|
if (node_match == false)
|
||||||
|
{
|
||||||
|
if (strlen(bdr_local_node_name.data))
|
||||||
|
{
|
||||||
|
log_error(_("local node BDR node name is \"%s\", expected: \"%s\""),
|
||||||
|
bdr_local_node_name.data,
|
||||||
|
config_file_options.node_name);
|
||||||
|
log_hint(_("\"node_name\" in repmgr.conf must match \"node_name\" in bdr.bdr_nodes"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
log_error(_("local node does not report BDR node name"));
|
||||||
|
log_hint(_("ensure this is an active BDR node"));
|
||||||
|
}
|
||||||
|
|
||||||
|
PQfinish(conn);
|
||||||
|
pfree(dbname);
|
||||||
|
termPQExpBuffer(&bdr_local_node_name);
|
||||||
|
exit(ERR_BAD_CONFIG);
|
||||||
|
}
|
||||||
|
|
||||||
|
termPQExpBuffer(&bdr_local_node_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check whether repmgr extension exists, and there are no non-BDR nodes registered */
|
||||||
|
extension_status = get_repmgr_extension_status(conn, NULL);
|
||||||
|
|
||||||
if (extension_status == REPMGR_UNKNOWN)
|
if (extension_status == REPMGR_UNKNOWN)
|
||||||
{
|
{
|
||||||
@@ -142,17 +184,10 @@ do_bdr_register(void)
|
|||||||
|
|
||||||
pfree(dbname);
|
pfree(dbname);
|
||||||
|
|
||||||
/* check for a matching BDR node */
|
if (bdr_node_has_repmgr_set(conn, config_file_options.node_name) == false)
|
||||||
{
|
{
|
||||||
bool node_exists = bdr_node_exists(conn, config_file_options.node_name);
|
log_debug("bdr_node_has_repmgr_set() = false");
|
||||||
|
bdr_node_set_repmgr_set(conn, config_file_options.node_name);
|
||||||
if (node_exists == false)
|
|
||||||
{
|
|
||||||
log_error(_("no BDR node with node_name \"%s\" found"), config_file_options.node_name);
|
|
||||||
log_hint(_("\"node_name\" in repmgr.conf must match \"node_name\" in bdr.bdr_nodes"));
|
|
||||||
PQfinish(conn);
|
|
||||||
exit(ERR_BAD_CONFIG);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -165,7 +200,7 @@ do_bdr_register(void)
|
|||||||
{
|
{
|
||||||
NodeInfoList local_node_records = T_NODE_INFO_LIST_INITIALIZER;
|
NodeInfoList local_node_records = T_NODE_INFO_LIST_INITIALIZER;
|
||||||
|
|
||||||
get_all_node_records(conn, &local_node_records);
|
(void) get_all_node_records(conn, &local_node_records);
|
||||||
|
|
||||||
if (local_node_records.node_count == 0)
|
if (local_node_records.node_count == 0)
|
||||||
{
|
{
|
||||||
@@ -177,6 +212,7 @@ do_bdr_register(void)
|
|||||||
if (bdr_nodes.node_count == 0)
|
if (bdr_nodes.node_count == 0)
|
||||||
{
|
{
|
||||||
log_error(_("unable to retrieve any BDR node records"));
|
log_error(_("unable to retrieve any BDR node records"));
|
||||||
|
log_detail("%s", PQerrorMessage(conn));
|
||||||
PQfinish(conn);
|
PQfinish(conn);
|
||||||
exit(ERR_BAD_CONFIG);
|
exit(ERR_BAD_CONFIG);
|
||||||
}
|
}
|
||||||
@@ -189,7 +225,7 @@ do_bdr_register(void)
|
|||||||
ExtensionStatus other_node_extension_status = REPMGR_UNKNOWN;
|
ExtensionStatus other_node_extension_status = REPMGR_UNKNOWN;
|
||||||
|
|
||||||
/* skip the local node */
|
/* skip the local node */
|
||||||
if (strncmp(node_info.node_name, bdr_cell->node_info->node_name, MAXLEN) == 0)
|
if (strncmp(node_info.node_name, bdr_cell->node_info->node_name, sizeof(node_info.node_name)) == 0)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -205,14 +241,14 @@ do_bdr_register(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* check repmgr schema exists, skip if not */
|
/* check repmgr schema exists, skip if not */
|
||||||
other_node_extension_status = get_repmgr_extension_status(bdr_node_conn);
|
other_node_extension_status = get_repmgr_extension_status(bdr_node_conn, NULL);
|
||||||
|
|
||||||
if (other_node_extension_status != REPMGR_INSTALLED)
|
if (other_node_extension_status != REPMGR_INSTALLED)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
get_all_node_records(bdr_node_conn, &existing_nodes);
|
(void) get_all_node_records(bdr_node_conn, &existing_nodes);
|
||||||
|
|
||||||
for (cell = existing_nodes.head; cell; cell = cell->next)
|
for (cell = existing_nodes.head; cell; cell = cell->next)
|
||||||
{
|
{
|
||||||
@@ -228,7 +264,35 @@ do_bdr_register(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Add the repmgr extension tables to a replication set */
|
/* Add the repmgr extension tables to a replication set */
|
||||||
add_extension_tables_to_bdr_replication_set(conn);
|
|
||||||
|
if (get_bdr_version_num() < 3)
|
||||||
|
{
|
||||||
|
add_extension_tables_to_bdr_replication_set(conn);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* this is the only table we need to replicate */
|
||||||
|
char *replication_set = get_default_bdr_replication_set(conn);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* this probably won't happen, but we need to be sure we're using
|
||||||
|
* the replication set metadata correctly...
|
||||||
|
*/
|
||||||
|
if (conn == NULL)
|
||||||
|
{
|
||||||
|
log_error(_("unable to retrieve default BDR replication set"));
|
||||||
|
log_hint(_("see preceding messages"));
|
||||||
|
log_debug("check query in get_default_bdr_replication_set()");
|
||||||
|
exit(ERR_BAD_CONFIG);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_table_in_bdr_replication_set(conn, "nodes", replication_set) == false)
|
||||||
|
{
|
||||||
|
add_table_to_bdr_replication_set(conn, "nodes", replication_set);
|
||||||
|
}
|
||||||
|
|
||||||
|
pfree(replication_set);
|
||||||
|
}
|
||||||
|
|
||||||
initPQExpBuffer(&event_details);
|
initPQExpBuffer(&event_details);
|
||||||
|
|
||||||
@@ -249,9 +313,9 @@ do_bdr_register(void)
|
|||||||
node_info.active = true;
|
node_info.active = true;
|
||||||
node_info.priority = config_file_options.priority;
|
node_info.priority = config_file_options.priority;
|
||||||
|
|
||||||
strncpy(node_info.node_name, config_file_options.node_name, MAXLEN);
|
strncpy(node_info.node_name, config_file_options.node_name, sizeof(node_info.node_name));
|
||||||
strncpy(node_info.location, config_file_options.location, MAXLEN);
|
strncpy(node_info.location, config_file_options.location, sizeof(node_info.location));
|
||||||
strncpy(node_info.conninfo, config_file_options.conninfo, MAXLEN);
|
strncpy(node_info.conninfo, config_file_options.conninfo, sizeof(node_info.conninfo));
|
||||||
|
|
||||||
if (record_status == RECORD_FOUND)
|
if (record_status == RECORD_FOUND)
|
||||||
{
|
{
|
||||||
@@ -275,7 +339,7 @@ do_bdr_register(void)
|
|||||||
* name set when the node was registered.
|
* name set when the node was registered.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (strncmp(node_info.node_name, config_file_options.node_name, MAXLEN) != 0)
|
if (strncmp(node_info.node_name, config_file_options.node_name, sizeof(node_info.node_name)) != 0)
|
||||||
{
|
{
|
||||||
log_error(_("a record for node %i is already registered with node_name \"%s\""),
|
log_error(_("a record for node %i is already registered with node_name \"%s\""),
|
||||||
config_file_options.node_id, node_info.node_name);
|
config_file_options.node_id, node_info.node_name);
|
||||||
@@ -387,7 +451,7 @@ do_bdr_unregister(void)
|
|||||||
exit(ERR_BAD_CONFIG);
|
exit(ERR_BAD_CONFIG);
|
||||||
}
|
}
|
||||||
|
|
||||||
extension_status = get_repmgr_extension_status(conn);
|
extension_status = get_repmgr_extension_status(conn, NULL);
|
||||||
if (extension_status != REPMGR_INSTALLED)
|
if (extension_status != REPMGR_INSTALLED)
|
||||||
{
|
{
|
||||||
log_error(_("repmgr is not installed on database \"%s\""), dbname);
|
log_error(_("repmgr is not installed on database \"%s\""), dbname);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* repmgr-action-bdr.h
|
* repmgr-action-bdr.h
|
||||||
* Copyright (c) 2ndQuadrant, 2010-2017
|
* Copyright (c) 2ndQuadrant, 2010-2019
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* repmgr-action-cluster.h
|
* repmgr-action-cluster.h
|
||||||
* Copyright (c) 2ndQuadrant, 2010-2017
|
* Copyright (c) 2ndQuadrant, 2010-2019
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -30,14 +30,14 @@ typedef struct
|
|||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
int node_id;
|
int node_id;
|
||||||
char node_name[MAXLEN];
|
char node_name[NAMEDATALEN];
|
||||||
t_node_status_rec **node_status_list;
|
t_node_status_rec **node_status_list;
|
||||||
} t_node_matrix_rec;
|
} t_node_matrix_rec;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
int node_id;
|
int node_id;
|
||||||
char node_name[MAXLEN];
|
char node_name[NAMEDATALEN];
|
||||||
t_node_matrix_rec **matrix_list_rec;
|
t_node_matrix_rec **matrix_list_rec;
|
||||||
} t_node_status_cube;
|
} t_node_status_cube;
|
||||||
|
|
||||||
|
|||||||
795
repmgr-action-daemon.c
Normal file
795
repmgr-action-daemon.c
Normal file
@@ -0,0 +1,795 @@
|
|||||||
|
/*
|
||||||
|
* repmgr-action-daemon.c
|
||||||
|
*
|
||||||
|
* Implements repmgrd actions for the repmgr command line utility
|
||||||
|
* Copyright (c) 2ndQuadrant, 2010-2019
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <signal.h>
|
||||||
|
#include <sys/stat.h> /* for stat() */
|
||||||
|
|
||||||
|
#include "repmgr.h"
|
||||||
|
|
||||||
|
#include "repmgr-client-global.h"
|
||||||
|
#include "repmgr-action-daemon.h"
|
||||||
|
|
||||||
|
#define REPMGR_DAEMON_STOP_START_WAIT 15
|
||||||
|
#define REPMGR_DAEMON_STATUS_START_HINT _("use \"repmgr daemon status\" to confirm that repmgrd was successfully started")
|
||||||
|
#define REPMGR_DAEMON_STATUS_STOP_HINT _("use \"repmgr daemon status\" to confirm that repmgrd was successfully stopped")
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Possibly also show:
|
||||||
|
* - repmgrd start time?
|
||||||
|
* - repmgrd mode
|
||||||
|
* - priority
|
||||||
|
* - whether promotion candidate (due to zero priority/different location)
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
STATUS_ID = 0,
|
||||||
|
STATUS_NAME,
|
||||||
|
STATUS_ROLE,
|
||||||
|
STATUS_PRIORITY,
|
||||||
|
STATUS_PG,
|
||||||
|
STATUS_RUNNING,
|
||||||
|
STATUS_PID,
|
||||||
|
STATUS_PAUSED,
|
||||||
|
STATUS_UPSTREAM_LAST_SEEN
|
||||||
|
} StatusHeader;
|
||||||
|
|
||||||
|
#define STATUS_HEADER_COUNT 9
|
||||||
|
|
||||||
|
struct ColHeader headers_status[STATUS_HEADER_COUNT];
|
||||||
|
|
||||||
|
static void fetch_node_records(PGconn *conn, NodeInfoList *node_list);
|
||||||
|
static void _do_repmgr_pause(bool pause);
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
do_daemon_status(void)
|
||||||
|
{
|
||||||
|
PGconn *conn = NULL;
|
||||||
|
NodeInfoList nodes = T_NODE_INFO_LIST_INITIALIZER;
|
||||||
|
NodeInfoListCell *cell = NULL;
|
||||||
|
int i;
|
||||||
|
RepmgrdInfo **repmgrd_info;
|
||||||
|
ItemList warnings = {NULL, NULL};
|
||||||
|
bool connection_error_found = false;
|
||||||
|
|
||||||
|
/* Connect to local database to obtain cluster connection data */
|
||||||
|
log_verbose(LOG_INFO, _("connecting to database"));
|
||||||
|
|
||||||
|
if (strlen(config_file_options.conninfo))
|
||||||
|
conn = establish_db_connection(config_file_options.conninfo, true);
|
||||||
|
else
|
||||||
|
conn = establish_db_connection_by_params(&source_conninfo, true);
|
||||||
|
|
||||||
|
fetch_node_records(conn, &nodes);
|
||||||
|
|
||||||
|
repmgrd_info = (RepmgrdInfo **) pg_malloc0(sizeof(RepmgrdInfo *) * nodes.node_count);
|
||||||
|
|
||||||
|
if (repmgrd_info == NULL)
|
||||||
|
{
|
||||||
|
log_error(_("unable to allocate memory"));
|
||||||
|
exit(ERR_OUT_OF_MEMORY);
|
||||||
|
}
|
||||||
|
|
||||||
|
strncpy(headers_status[STATUS_ID].title, _("ID"), MAXLEN);
|
||||||
|
strncpy(headers_status[STATUS_NAME].title, _("Name"), MAXLEN);
|
||||||
|
strncpy(headers_status[STATUS_ROLE].title, _("Role"), MAXLEN);
|
||||||
|
|
||||||
|
if (runtime_options.compact == true)
|
||||||
|
strncpy(headers_status[STATUS_PRIORITY].title, _("Prio."), MAXLEN);
|
||||||
|
else
|
||||||
|
strncpy(headers_status[STATUS_PRIORITY].title, _("Priority"), MAXLEN);
|
||||||
|
|
||||||
|
strncpy(headers_status[STATUS_PG].title, _("Status"), MAXLEN);
|
||||||
|
strncpy(headers_status[STATUS_RUNNING].title, _("repmgrd"), MAXLEN);
|
||||||
|
strncpy(headers_status[STATUS_PID].title, _("PID"), MAXLEN);
|
||||||
|
strncpy(headers_status[STATUS_PAUSED].title, _("Paused?"), MAXLEN);
|
||||||
|
|
||||||
|
if (runtime_options.compact == true)
|
||||||
|
strncpy(headers_status[STATUS_UPSTREAM_LAST_SEEN].title, _("Upstr. last"), MAXLEN);
|
||||||
|
else
|
||||||
|
strncpy(headers_status[STATUS_UPSTREAM_LAST_SEEN].title, _("Upstream last seen"), MAXLEN);
|
||||||
|
|
||||||
|
|
||||||
|
for (i = 0; i < STATUS_HEADER_COUNT; i++)
|
||||||
|
{
|
||||||
|
headers_status[i].max_length = strlen(headers_status[i].title);
|
||||||
|
headers_status[i].display = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
|
||||||
|
for (cell = nodes.head; cell; cell = cell->next)
|
||||||
|
{
|
||||||
|
int j;
|
||||||
|
PQExpBufferData buf;
|
||||||
|
|
||||||
|
repmgrd_info[i] = pg_malloc0(sizeof(RepmgrdInfo));
|
||||||
|
repmgrd_info[i]->node_id = cell->node_info->node_id;
|
||||||
|
repmgrd_info[i]->pid = UNKNOWN_PID;
|
||||||
|
repmgrd_info[i]->recovery_type = RECTYPE_UNKNOWN;
|
||||||
|
repmgrd_info[i]->paused = false;
|
||||||
|
repmgrd_info[i]->running = false;
|
||||||
|
repmgrd_info[i]->pg_running = true;
|
||||||
|
repmgrd_info[i]->wal_paused_pending_wal = false;
|
||||||
|
repmgrd_info[i]->upstream_last_seen = -1;
|
||||||
|
|
||||||
|
cell->node_info->conn = establish_db_connection_quiet(cell->node_info->conninfo);
|
||||||
|
|
||||||
|
if (PQstatus(cell->node_info->conn) != CONNECTION_OK)
|
||||||
|
{
|
||||||
|
connection_error_found = true;
|
||||||
|
|
||||||
|
if (runtime_options.verbose)
|
||||||
|
{
|
||||||
|
char error[MAXLEN];
|
||||||
|
|
||||||
|
strncpy(error, PQerrorMessage(cell->node_info->conn), MAXLEN);
|
||||||
|
|
||||||
|
item_list_append_format(&warnings,
|
||||||
|
"when attempting to connect to node \"%s\" (ID: %i), following error encountered :\n\"%s\"",
|
||||||
|
cell->node_info->node_name, cell->node_info->node_id, trim(error));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
item_list_append_format(&warnings,
|
||||||
|
"unable to connect to node \"%s\" (ID: %i)",
|
||||||
|
cell->node_info->node_name, cell->node_info->node_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
repmgrd_info[i]->pg_running = false;
|
||||||
|
maxlen_snprintf(repmgrd_info[i]->pg_running_text, "%s", _("not running"));
|
||||||
|
maxlen_snprintf(repmgrd_info[i]->repmgrd_running, "%s", _("n/a"));
|
||||||
|
maxlen_snprintf(repmgrd_info[i]->pid_text, "%s", _("n/a"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
maxlen_snprintf(repmgrd_info[i]->pg_running_text, "%s", _("running"));
|
||||||
|
|
||||||
|
repmgrd_info[i]->pid = repmgrd_get_pid(cell->node_info->conn);
|
||||||
|
|
||||||
|
repmgrd_info[i]->running = repmgrd_is_running(cell->node_info->conn);
|
||||||
|
|
||||||
|
if (repmgrd_info[i]->running == true)
|
||||||
|
{
|
||||||
|
maxlen_snprintf(repmgrd_info[i]->repmgrd_running, "%s", _("running"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
maxlen_snprintf(repmgrd_info[i]->repmgrd_running, "%s", _("not running"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (repmgrd_info[i]->pid == UNKNOWN_PID)
|
||||||
|
{
|
||||||
|
maxlen_snprintf(repmgrd_info[i]->pid_text, "%s", _("n/a"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
maxlen_snprintf(repmgrd_info[i]->pid_text, "%i", repmgrd_info[i]->pid);
|
||||||
|
}
|
||||||
|
|
||||||
|
repmgrd_info[i]->paused = repmgrd_is_paused(cell->node_info->conn);
|
||||||
|
|
||||||
|
repmgrd_info[i]->recovery_type = get_recovery_type(cell->node_info->conn);
|
||||||
|
|
||||||
|
if (repmgrd_info[i]->recovery_type == RECTYPE_STANDBY)
|
||||||
|
{
|
||||||
|
repmgrd_info[i]->wal_paused_pending_wal = is_wal_replay_paused(cell->node_info->conn, true);
|
||||||
|
|
||||||
|
if (repmgrd_info[i]->wal_paused_pending_wal == true)
|
||||||
|
{
|
||||||
|
item_list_append_format(&warnings,
|
||||||
|
_("WAL replay is paused on node \"%s\" (ID: %i) with WAL replay pending; this node cannot be manually promoted until WAL replay is resumed"),
|
||||||
|
cell->node_info->node_name, cell->node_info->node_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
repmgrd_info[i]->upstream_last_seen = get_upstream_last_seen(cell->node_info->conn, cell->node_info->type);
|
||||||
|
if (repmgrd_info[i]->upstream_last_seen < 0)
|
||||||
|
{
|
||||||
|
maxlen_snprintf(repmgrd_info[i]->upstream_last_seen_text, "%s", _("n/a"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (runtime_options.compact == true)
|
||||||
|
{
|
||||||
|
maxlen_snprintf(repmgrd_info[i]->upstream_last_seen_text, _("%i sec(s) ago"), repmgrd_info[i]->upstream_last_seen);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
maxlen_snprintf(repmgrd_info[i]->upstream_last_seen_text, _("%i second(s) ago"), repmgrd_info[i]->upstream_last_seen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PQfinish(cell->node_info->conn);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
headers_status[STATUS_NAME].cur_length = strlen(cell->node_info->node_name);
|
||||||
|
headers_status[STATUS_ROLE].cur_length = strlen(get_node_type_string(cell->node_info->type));
|
||||||
|
|
||||||
|
initPQExpBuffer(&buf);
|
||||||
|
appendPQExpBuffer(&buf, "%i", cell->node_info->priority);
|
||||||
|
headers_status[STATUS_PRIORITY].cur_length = strlen(buf.data);
|
||||||
|
termPQExpBuffer(&buf);
|
||||||
|
|
||||||
|
headers_status[STATUS_PID].cur_length = strlen(repmgrd_info[i]->pid_text);
|
||||||
|
headers_status[STATUS_RUNNING].cur_length = strlen(repmgrd_info[i]->repmgrd_running);
|
||||||
|
headers_status[STATUS_PG].cur_length = strlen(repmgrd_info[i]->pg_running_text);
|
||||||
|
|
||||||
|
headers_status[STATUS_UPSTREAM_LAST_SEEN].cur_length = strlen(repmgrd_info[i]->upstream_last_seen_text);
|
||||||
|
|
||||||
|
for (j = 0; j < STATUS_HEADER_COUNT; j++)
|
||||||
|
{
|
||||||
|
if (headers_status[j].cur_length > headers_status[j].max_length)
|
||||||
|
{
|
||||||
|
headers_status[j].max_length = headers_status[j].cur_length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Print column header row (text mode only) */
|
||||||
|
if (runtime_options.output_mode == OM_TEXT)
|
||||||
|
{
|
||||||
|
print_status_header(STATUS_HEADER_COUNT, headers_status);
|
||||||
|
}
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
|
||||||
|
for (cell = nodes.head; cell; cell = cell->next)
|
||||||
|
{
|
||||||
|
if (runtime_options.output_mode == OM_CSV)
|
||||||
|
{
|
||||||
|
int running = repmgrd_info[i]->running ? 1 : 0;
|
||||||
|
int paused = repmgrd_info[i]->paused ? 1 : 0;
|
||||||
|
|
||||||
|
/* If PostgreSQL is not running, repmgrd status is unknown */
|
||||||
|
if (repmgrd_info[i]->pg_running == false)
|
||||||
|
{
|
||||||
|
running = -1;
|
||||||
|
paused = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("%i,%s,%s,%i,%i,%i,%i,%i,%i\n",
|
||||||
|
cell->node_info->node_id,
|
||||||
|
cell->node_info->node_name,
|
||||||
|
get_node_type_string(cell->node_info->type),
|
||||||
|
repmgrd_info[i]->pg_running ? 1 : 0,
|
||||||
|
running,
|
||||||
|
repmgrd_info[i]->pid,
|
||||||
|
paused,
|
||||||
|
cell->node_info->priority,
|
||||||
|
repmgrd_info[i]->pid == UNKNOWN_PID
|
||||||
|
? -1
|
||||||
|
: repmgrd_info[i]->upstream_last_seen);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf(" %-*i ", headers_status[STATUS_ID].max_length, cell->node_info->node_id);
|
||||||
|
printf("| %-*s ", headers_status[STATUS_NAME].max_length, cell->node_info->node_name);
|
||||||
|
printf("| %-*s ", headers_status[STATUS_ROLE].max_length, get_node_type_string(cell->node_info->type));
|
||||||
|
printf("| %-*i ", headers_status[STATUS_PRIORITY].max_length, cell->node_info->priority);
|
||||||
|
|
||||||
|
printf("| %-*s ", headers_status[STATUS_PG].max_length, repmgrd_info[i]->pg_running_text);
|
||||||
|
printf("| %-*s ", headers_status[STATUS_RUNNING].max_length, repmgrd_info[i]->repmgrd_running);
|
||||||
|
printf("| %-*s ", headers_status[STATUS_PID].max_length, repmgrd_info[i]->pid_text);
|
||||||
|
|
||||||
|
if (repmgrd_info[i]->pid == UNKNOWN_PID)
|
||||||
|
{
|
||||||
|
printf("| %-*s ", headers_status[STATUS_PAUSED].max_length, _("n/a"));
|
||||||
|
printf("| %-*s ", headers_status[STATUS_UPSTREAM_LAST_SEEN].max_length, _("n/a"));
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("| %-*s ", headers_status[STATUS_PAUSED].max_length, repmgrd_info[i]->paused ? _("yes") : _("no"));
|
||||||
|
|
||||||
|
printf("| %-*s ", headers_status[STATUS_UPSTREAM_LAST_SEEN].max_length, repmgrd_info[i]->upstream_last_seen_text);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
pfree(repmgrd_info[i]);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
pfree(repmgrd_info);
|
||||||
|
|
||||||
|
/* emit any warnings */
|
||||||
|
|
||||||
|
if (warnings.head != NULL && runtime_options.terse == false && runtime_options.output_mode != OM_CSV)
|
||||||
|
{
|
||||||
|
ItemListCell *cell = NULL;
|
||||||
|
|
||||||
|
printf(_("\nWARNING: following issues were detected\n"));
|
||||||
|
for (cell = warnings.head; cell; cell = cell->next)
|
||||||
|
{
|
||||||
|
printf(_(" - %s\n"), cell->string);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (runtime_options.verbose == false && connection_error_found == true)
|
||||||
|
{
|
||||||
|
log_hint(_("execute with --verbose option to see connection error messages"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
do_daemon_pause(void)
|
||||||
|
{
|
||||||
|
_do_repmgr_pause(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
do_daemon_unpause(void)
|
||||||
|
{
|
||||||
|
_do_repmgr_pause(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
_do_repmgr_pause(bool pause)
|
||||||
|
{
|
||||||
|
PGconn *conn = NULL;
|
||||||
|
NodeInfoList nodes = T_NODE_INFO_LIST_INITIALIZER;
|
||||||
|
NodeInfoListCell *cell = NULL;
|
||||||
|
int i;
|
||||||
|
int error_nodes = 0;
|
||||||
|
|
||||||
|
/* Connect to local database to obtain cluster connection data */
|
||||||
|
log_verbose(LOG_INFO, _("connecting to database"));
|
||||||
|
|
||||||
|
if (strlen(config_file_options.conninfo))
|
||||||
|
conn = establish_db_connection(config_file_options.conninfo, true);
|
||||||
|
else
|
||||||
|
conn = establish_db_connection_by_params(&source_conninfo, true);
|
||||||
|
|
||||||
|
fetch_node_records(conn, &nodes);
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
|
||||||
|
for (cell = nodes.head; cell; cell = cell->next)
|
||||||
|
{
|
||||||
|
log_verbose(LOG_DEBUG, "pausing node %i (%s)",
|
||||||
|
cell->node_info->node_id,
|
||||||
|
cell->node_info->node_name);
|
||||||
|
cell->node_info->conn = establish_db_connection_quiet(cell->node_info->conninfo);
|
||||||
|
|
||||||
|
if (PQstatus(cell->node_info->conn) != CONNECTION_OK)
|
||||||
|
{
|
||||||
|
log_warning(_("unable to connect to node %i"),
|
||||||
|
cell->node_info->node_id);
|
||||||
|
error_nodes++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (runtime_options.dry_run == true)
|
||||||
|
{
|
||||||
|
if (pause == true)
|
||||||
|
{
|
||||||
|
log_info(_("would pause node %i (%s) "),
|
||||||
|
cell->node_info->node_id,
|
||||||
|
cell->node_info->node_name);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
log_info(_("would unpause node %i (%s) "),
|
||||||
|
cell->node_info->node_id,
|
||||||
|
cell->node_info->node_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bool success = repmgrd_pause(cell->node_info->conn, pause);
|
||||||
|
|
||||||
|
if (success == false)
|
||||||
|
error_nodes++;
|
||||||
|
|
||||||
|
log_notice(_("node %i (%s) %s"),
|
||||||
|
cell->node_info->node_id,
|
||||||
|
cell->node_info->node_name,
|
||||||
|
success == true
|
||||||
|
? pause == true ? "paused" : "unpaused"
|
||||||
|
: pause == true ? "not paused" : "not unpaused");
|
||||||
|
}
|
||||||
|
PQfinish(cell->node_info->conn);
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error_nodes > 0)
|
||||||
|
{
|
||||||
|
if (pause == true)
|
||||||
|
{
|
||||||
|
log_error(_("unable to pause %i node(s)"), error_nodes);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
log_error(_("unable to unpause %i node(s)"), error_nodes);
|
||||||
|
}
|
||||||
|
|
||||||
|
log_hint(_("execute \"repmgr daemon status\" to view current status"));
|
||||||
|
|
||||||
|
exit(ERR_REPMGRD_PAUSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
exit(SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
fetch_node_records(PGconn *conn, NodeInfoList *node_list)
|
||||||
|
{
|
||||||
|
bool success = get_all_node_records(conn, node_list);
|
||||||
|
|
||||||
|
if (success == false)
|
||||||
|
{
|
||||||
|
/* get_all_node_records() will display any error message */
|
||||||
|
PQfinish(conn);
|
||||||
|
exit(ERR_BAD_CONFIG);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node_list->node_count == 0)
|
||||||
|
{
|
||||||
|
log_error(_("no node records were found"));
|
||||||
|
log_hint(_("ensure at least one node is registered"));
|
||||||
|
PQfinish(conn);
|
||||||
|
exit(ERR_BAD_CONFIG);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
do_daemon_start(void)
|
||||||
|
{
|
||||||
|
PGconn *conn = NULL;
|
||||||
|
PQExpBufferData repmgrd_command;
|
||||||
|
PQExpBufferData output_buf;
|
||||||
|
bool success;
|
||||||
|
|
||||||
|
if (config_file_options.repmgrd_service_start_command[0] == '\0')
|
||||||
|
{
|
||||||
|
log_error(_("\"repmgrd_service_start_command\" is not set"));
|
||||||
|
log_hint(_("set \"repmgrd_service_start_command\" in \"repmgr.conf\""));
|
||||||
|
exit(ERR_BAD_CONFIG);
|
||||||
|
}
|
||||||
|
|
||||||
|
log_verbose(LOG_INFO, _("connecting to local node"));
|
||||||
|
|
||||||
|
conn = establish_db_connection(config_file_options.conninfo, false);
|
||||||
|
|
||||||
|
if (PQstatus(conn) != CONNECTION_OK)
|
||||||
|
{
|
||||||
|
/* TODO: if PostgreSQL is not available, have repmgrd loop and retry connection */
|
||||||
|
log_error(_("unable to connect to local node"));
|
||||||
|
log_detail(_("PostgreSQL must be running before \"repmgrd\" can be started"));
|
||||||
|
exit(ERR_DB_CONN);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* if local connection available, check if repmgr.so is installed, and
|
||||||
|
* whether repmgrd is running
|
||||||
|
*/
|
||||||
|
check_shared_library(conn);
|
||||||
|
|
||||||
|
if (is_repmgrd_running(conn) == true)
|
||||||
|
{
|
||||||
|
pid_t pid = UNKNOWN_PID;
|
||||||
|
|
||||||
|
log_error(_("repmgrd appears to be running already"));
|
||||||
|
|
||||||
|
pid = repmgrd_get_pid(conn);
|
||||||
|
|
||||||
|
if (pid != UNKNOWN_PID)
|
||||||
|
log_detail(_("repmgrd PID is %i"), pid);
|
||||||
|
else
|
||||||
|
log_warning(_("unable to determine repmgrd PID"));
|
||||||
|
|
||||||
|
PQfinish(conn);
|
||||||
|
exit(ERR_REPMGRD_SERVICE);
|
||||||
|
}
|
||||||
|
|
||||||
|
PQfinish(conn);
|
||||||
|
|
||||||
|
|
||||||
|
initPQExpBuffer(&repmgrd_command);
|
||||||
|
appendPQExpBufferStr(&repmgrd_command,
|
||||||
|
config_file_options.repmgrd_service_start_command);
|
||||||
|
|
||||||
|
if (runtime_options.dry_run == true)
|
||||||
|
{
|
||||||
|
log_info(_("prerequisites for starting repmgrd met"));
|
||||||
|
log_detail("following command would be executed:\n %s", repmgrd_command.data);
|
||||||
|
exit(SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
log_notice(_("executing: \"%s\""), repmgrd_command.data);
|
||||||
|
|
||||||
|
initPQExpBuffer(&output_buf);
|
||||||
|
|
||||||
|
success = local_command(repmgrd_command.data, &output_buf);
|
||||||
|
termPQExpBuffer(&repmgrd_command);
|
||||||
|
|
||||||
|
if (success == false)
|
||||||
|
{
|
||||||
|
log_error(_("unable to start repmgrd"));
|
||||||
|
if (output_buf.data[0] != '\0')
|
||||||
|
log_detail("%s", output_buf.data);
|
||||||
|
termPQExpBuffer(&output_buf);
|
||||||
|
exit(ERR_REPMGRD_SERVICE);
|
||||||
|
}
|
||||||
|
|
||||||
|
termPQExpBuffer(&output_buf);
|
||||||
|
|
||||||
|
if (runtime_options.no_wait == true || runtime_options.wait == 0)
|
||||||
|
{
|
||||||
|
log_hint(REPMGR_DAEMON_STATUS_START_HINT);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
int timeout = REPMGR_DAEMON_STOP_START_WAIT;
|
||||||
|
|
||||||
|
if (runtime_options.wait_provided)
|
||||||
|
timeout = runtime_options.wait;
|
||||||
|
|
||||||
|
conn = establish_db_connection(config_file_options.conninfo, false);
|
||||||
|
|
||||||
|
if (PQstatus(conn) != CONNECTION_OK)
|
||||||
|
{
|
||||||
|
log_notice(_("unable to connect to local node"));
|
||||||
|
log_hint(REPMGR_DAEMON_STATUS_START_HINT);
|
||||||
|
exit(ERR_DB_CONN);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
if (is_repmgrd_running(conn) == true)
|
||||||
|
{
|
||||||
|
log_notice(_("repmgrd was successfully started"));
|
||||||
|
PQfinish(conn);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == timeout)
|
||||||
|
{
|
||||||
|
PQfinish(conn);
|
||||||
|
log_error(_("repmgrd does not appear to have started after %i seconds"),
|
||||||
|
timeout);
|
||||||
|
log_hint(REPMGR_DAEMON_STATUS_START_HINT);
|
||||||
|
exit(ERR_REPMGRD_SERVICE);
|
||||||
|
}
|
||||||
|
|
||||||
|
log_debug("sleeping 1 second; %i of %i attempts to determine if repmgrd is running",
|
||||||
|
i, runtime_options.wait);
|
||||||
|
sleep(1);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void do_daemon_stop(void)
|
||||||
|
{
|
||||||
|
PGconn *conn = NULL;
|
||||||
|
PQExpBufferData repmgrd_command;
|
||||||
|
PQExpBufferData output_buf;
|
||||||
|
bool success;
|
||||||
|
bool have_db_connection = true;
|
||||||
|
pid_t pid = UNKNOWN_PID;
|
||||||
|
|
||||||
|
if (config_file_options.repmgrd_service_stop_command[0] == '\0')
|
||||||
|
{
|
||||||
|
log_error(_("\"repmgrd_service_stop_command\" is not set"));
|
||||||
|
log_hint(_("set \"repmgrd_service_stop_command\" in \"repmgr.conf\""));
|
||||||
|
exit(ERR_BAD_CONFIG);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* if local connection available, check if repmgr.so is installed, and
|
||||||
|
* whether repmgrd is running
|
||||||
|
*/
|
||||||
|
log_verbose(LOG_INFO, _("connecting to local node"));
|
||||||
|
|
||||||
|
conn = establish_db_connection(config_file_options.conninfo, false);
|
||||||
|
|
||||||
|
if (PQstatus(conn) != CONNECTION_OK)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* a PostgreSQL connection is not required to stop repmgrd,
|
||||||
|
*/
|
||||||
|
log_warning(_("unable to connect to local node"));
|
||||||
|
have_db_connection = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
check_shared_library(conn);
|
||||||
|
|
||||||
|
if (is_repmgrd_running(conn) == false)
|
||||||
|
{
|
||||||
|
log_error(_("repmgrd appears to be stopped already"));
|
||||||
|
PQfinish(conn);
|
||||||
|
exit(ERR_REPMGRD_SERVICE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Attempt to fetch the PID, in case we need it later */
|
||||||
|
pid = repmgrd_get_pid(conn);
|
||||||
|
log_debug("retrieved pid is %i", pid);
|
||||||
|
}
|
||||||
|
|
||||||
|
PQfinish(conn);
|
||||||
|
|
||||||
|
initPQExpBuffer(&repmgrd_command);
|
||||||
|
|
||||||
|
appendPQExpBufferStr(&repmgrd_command,
|
||||||
|
config_file_options.repmgrd_service_stop_command);
|
||||||
|
|
||||||
|
if (runtime_options.dry_run == true)
|
||||||
|
{
|
||||||
|
log_info(_("prerequisites for stopping repmgrd met"));
|
||||||
|
log_detail("following command would be executed:\n %s", repmgrd_command.data);
|
||||||
|
exit(SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
log_notice(_("executing: \"%s\""), repmgrd_command.data);
|
||||||
|
|
||||||
|
initPQExpBuffer(&output_buf);
|
||||||
|
|
||||||
|
success = local_command(repmgrd_command.data, &output_buf);
|
||||||
|
termPQExpBuffer(&repmgrd_command);
|
||||||
|
|
||||||
|
if (success == false)
|
||||||
|
{
|
||||||
|
log_error(_("unable to stop repmgrd"));
|
||||||
|
if (output_buf.data[0] != '\0')
|
||||||
|
log_detail("%s", output_buf.data);
|
||||||
|
termPQExpBuffer(&output_buf);
|
||||||
|
exit(ERR_REPMGRD_SERVICE);
|
||||||
|
}
|
||||||
|
|
||||||
|
termPQExpBuffer(&output_buf);
|
||||||
|
|
||||||
|
if (runtime_options.no_wait == true || runtime_options.wait == 0)
|
||||||
|
{
|
||||||
|
if (have_db_connection == true)
|
||||||
|
log_hint(REPMGR_DAEMON_STATUS_STOP_HINT);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
int timeout = REPMGR_DAEMON_STOP_START_WAIT;
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
if (pid == UNKNOWN_PID)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* XXX attempt to get pidfile from config
|
||||||
|
* and get contents
|
||||||
|
* ( see check_and_create_pid_file() )
|
||||||
|
* if PID still unknown, exit here
|
||||||
|
*/
|
||||||
|
log_warning(_("unable to determine repmgrd PID"));
|
||||||
|
|
||||||
|
if (have_db_connection == true)
|
||||||
|
log_hint(REPMGR_DAEMON_STATUS_STOP_HINT);
|
||||||
|
|
||||||
|
exit(ERR_REPMGRD_SERVICE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (runtime_options.wait_provided)
|
||||||
|
timeout = runtime_options.wait;
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
if (kill(pid, 0) == -1)
|
||||||
|
{
|
||||||
|
if (errno == ESRCH)
|
||||||
|
{
|
||||||
|
log_notice(_("repmgrd was successfully stopped"));
|
||||||
|
exit(SUCCESS);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
log_error(_("unable to determine status of process with PID %i"), pid);
|
||||||
|
log_detail("%s", strerror(errno));
|
||||||
|
exit(ERR_REPMGRD_SERVICE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (i == timeout)
|
||||||
|
{
|
||||||
|
log_error(_("repmgrd does not appear to have stopped after %i seconds"),
|
||||||
|
timeout);
|
||||||
|
|
||||||
|
if (have_db_connection == true)
|
||||||
|
log_hint(REPMGR_DAEMON_STATUS_START_HINT);
|
||||||
|
|
||||||
|
exit(ERR_REPMGRD_SERVICE);
|
||||||
|
}
|
||||||
|
|
||||||
|
log_debug("sleeping 1 second; %i of %i attempts to determine if repmgrd with PID %i is running",
|
||||||
|
i, timeout, pid);
|
||||||
|
sleep(1);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void do_daemon_help(void)
|
||||||
|
{
|
||||||
|
print_help_header();
|
||||||
|
|
||||||
|
printf(_("Usage:\n"));
|
||||||
|
printf(_(" %s [OPTIONS] daemon status\n"), progname());
|
||||||
|
printf(_(" %s [OPTIONS] daemon pause\n"), progname());
|
||||||
|
printf(_(" %s [OPTIONS] daemon unpause\n"), progname());
|
||||||
|
printf(_(" %s [OPTIONS] daemon start\n"), progname());
|
||||||
|
printf(_(" %s [OPTIONS] daemon stop\n"), progname());
|
||||||
|
puts("");
|
||||||
|
|
||||||
|
printf(_("DAEMON STATUS\n"));
|
||||||
|
puts("");
|
||||||
|
printf(_(" \"daemon status\" shows the status of repmgrd on each node in the cluster\n"));
|
||||||
|
puts("");
|
||||||
|
printf(_(" --csv emit output as CSV\n"));
|
||||||
|
printf(_(" --verbose show text of database connection error messages\n"));
|
||||||
|
puts("");
|
||||||
|
|
||||||
|
printf(_("DAEMON START\n"));
|
||||||
|
puts("");
|
||||||
|
printf(_(" \"daemon start\" attempts to start repmgrd\n"));
|
||||||
|
puts("");
|
||||||
|
printf(_(" --dry-run check prerequisites but don't start repmgrd\n"));
|
||||||
|
printf(_(" -w/--wait wait for repmgrd to start (default: %i seconds)\n"), REPMGR_DAEMON_STOP_START_WAIT);
|
||||||
|
printf(_(" --no-wait don't wait for repmgrd to start\n"));
|
||||||
|
puts("");
|
||||||
|
|
||||||
|
printf(_("DAEMON STOP\n"));
|
||||||
|
puts("");
|
||||||
|
printf(_(" \"daemon stop\" attempts to stop repmgrd\n"));
|
||||||
|
puts("");
|
||||||
|
printf(_(" --dry-run check prerequisites but don't stop repmgrd\n"));
|
||||||
|
printf(_(" -w/--wait wait for repmgrd to stop (default: %i seconds)\n"), REPMGR_DAEMON_STOP_START_WAIT);
|
||||||
|
printf(_(" --no-wait don't wait for repmgrd to stop\n"));
|
||||||
|
puts("");
|
||||||
|
|
||||||
|
printf(_("DAEMON PAUSE\n"));
|
||||||
|
puts("");
|
||||||
|
printf(_(" \"daemon pause\" instructs repmgrd on each node to pause failover detection\n"));
|
||||||
|
puts("");
|
||||||
|
printf(_(" --dry-run check if nodes are reachable but don't pause repmgrd\n"));
|
||||||
|
puts("");
|
||||||
|
|
||||||
|
printf(_("DAEMON UNPAUSE\n"));
|
||||||
|
puts("");
|
||||||
|
printf(_(" \"daemon unpause\" instructs repmgrd on each node to resume failover detection\n"));
|
||||||
|
puts("");
|
||||||
|
printf(_(" --dry-run check if nodes are reachable but don't unpause repmgrd\n"));
|
||||||
|
puts("");
|
||||||
|
|
||||||
|
puts("");
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user