| 204 | | |
| 205 | | |
| 206 | | |
| | 204 | == Promotion and failover |
| | 205 | |
| | 206 | За да се демонстрира промена на лидерот во системот, се симулира пад на примарниот сервер и рачно се промовира standby серверот. Во оваа поставеност примарниот PostgreSQL сервер работи на PC, додека standby серверот работи на вториот компјутер во истата локална мрежа. |
| | 207 | Целта на овој тест е да се прикаже дека standby серверот може да ја преземе улогата на primary сервер, а стариот primary потоа да се врати како нов standby сервер. |
| | 208 | |
| | 209 | |
| | 210 | === Симулирање пад на primary серверот |
| | 211 | |
| | 212 | На PC се запира примарниот PostgreSQL контејнер: |
| | 213 | |
| | 214 | {{{ docker compose down }}} |
| | 215 | |
| | 216 | Со ова примарниот сервер повеќе не е достапен. Бидејќи standby серверот на вториот компјутер веќе ги примал WAL записите од примарниот сервер, тој може да се промовира во нов primary сервер. |
| | 217 | По запирањето на primary серверот, на standby серверот се појавуваат логови кои покажуваат дека streaming replication конекцијата е прекината: |
| | 218 | {{{ |
| | 219 | postgres-replica | 2026-05-10 22:35:01.071 UTC [33] LOG: replication terminated by primary server |
| | 220 | postgres-replica | 2026-05-10 22:35:01.071 UTC [33] DETAIL: End of WAL reached on timeline 1 at 0/4000710. |
| | 221 | postgres-replica | 2026-05-10 22:35:01.072 UTC [33] FATAL: could not send end-of-streaming message to primary: server closed the connection unexpectedly |
| | 222 | postgres-replica | This probably means the server terminated abnormally |
| | 223 | postgres-replica | before or while processing the request. |
| | 224 | postgres-replica | invalid socket |
| | 225 | postgres-replica | no COPY in progress |
| | 226 | postgres-replica | 2026-05-10 22:35:01.072 UTC [32] LOG: invalid record length at 0/4000710: expected at least 24, got 0 |
| | 227 | postgres-replica | 2026-05-10 22:35:01.085 UTC [43] FATAL: streaming replication receiver "walreceiver" could not connect to the primary server: connection to server at "192.168.1.219", port 5432 failed: FATAL: the database system is shutting down |
| | 228 | postgres-replica | 2026-05-10 22:35:01.085 UTC [32] LOG: waiting for WAL to become available at 0/4000728 |
| | 229 | postgres-replica | 2026-05-10 22:35:06.503 UTC [30] LOG: restartpoint starting: time |
| | 230 | postgres-replica | 2026-05-10 22:35:06.511 UTC [30] LOG: restartpoint complete: wrote 0 buffers (0.0%), wrote 0 SLRU buffers; 0 WAL file(s) added, 0 removed, 0 recycled; write=0.001 s, sync=0.001 s, total=0.008 s; sync files=0, longest=0.000 s, average=0.000 s; distance=0 kB, estimate=13271 kB; lsn=0/4000698, redo lsn=0/4000698 |
| | 231 | postgres-replica | 2026-05-10 22:35:06.511 UTC [30] LOG: recovery restart point at 0/4000698 |
| | 232 | postgres-replica | 2026-05-10 22:35:06.511 UTC [30] DETAIL: Last completed transaction was at log time 2026-05-10 22:13:03.759754+00. |
| | 233 | |
| | 234 | }}} |
| | 235 | |
| | 236 | Овие логови покажуваат дека standby серверот ја изгубил конекцијата со primary серверот и чека нови WAL записи. Ова е очекувано однесување, бидејќи primary контејнерот е запрен. |
| | 237 | |
| | 238 | Дополнително, може да се провери дека повеќе нема активен WAL receiver: |
| | 239 | |
| | 240 | {{{ |
| | 241 | film_rental=# SELECT status, sender_host, sender_port, latest_end_lsn, latest_end_time FROM pg_stat_wal_receiver; |
| | 242 | status | sender_host | sender_port | latest_end_lsn | latest_end_time |
| | 243 | --------+-------------+-------------+----------------+----------------- |
| | 244 | (0 rows) |
| | 245 | }}} |
| | 246 | |
| | 247 | Резултатот '''(0 rows)''' означува дека standby серверот во тој момент нема активна WAL receiver конекција кон primary серверот. |
| | 248 | |
| | 249 | |
| | 250 | |
| | 251 | === Promotion на standby серверот |
| | 252 | |
| | 253 | Promotion се извршува на standby серверот со командата: |
| | 254 | {{{ |
| | 255 | film_rental=# SELECT pg_promote(); |
| | 256 | pg_promote |
| | 257 | ------------ |
| | 258 | t |
| | 259 | (1 row) |
| | 260 | }}} |
| | 261 | По promotion се проверува дали серверот повеќе не е во recovery режим: |
| | 262 | |
| | 263 | {{{ |
| | 264 | film_rental=# SELECT pg_is_in_recovery(); |
| | 265 | pg_is_in_recovery |
| | 266 | ------------------- |
| | 267 | f |
| | 268 | (1 row) |
| | 269 | }}} |
| | 270 | |
| | 271 | Вредноста f означува дека серверот повеќе не работи како standby, туку е промовиран во normal/primary режим и може да прима write операции. |
| | 272 | |
| | 273 | |
| | 274 | === Враќање на стариот primary како standby |
| | 275 | |
| | 276 | По promotion, стариот primary сервер на PC не смее само повторно да се стартува како primary. Во тој случај би постоеле два сервери кои можат да примаат write операции, што може да доведе до split-brain ситуација и неконзистентни податоци. |
| | 277 | Затоа стариот primary треба повторно да се иницијализира како standby сервер кој ќе го следи новиот primary сервер. |
| | 278 | На PC прво се отстранува старата локална PostgreSQL data содржина или Docker volume што го користел стариот primary. Потоа се прави нов pg_basebackup од промовираниот standby сервер, кој сега ја има улогата на primary: |
| | 279 | |
| | 280 | {{{ |
| | 281 | pg_basebackup -h 192.168.1.103 -p 5433 -U replicator -D ./data/18/docker -P -v -R |
| | 282 | Password: |
| | 283 | pg_basebackup: initiating base backup, waiting for checkpoint to complete |
| | 284 | pg_basebackup: checkpoint completed |
| | 285 | pg_basebackup: write-ahead log start point: 0/5000028 on timeline 2 |
| | 286 | pg_basebackup: starting background WAL receiver |
| | 287 | pg_basebackup: created temporary replication slot "pg_basebackup_146" |
| | 288 | 34298/34298 kB (100%), 1/1 tablespace |
| | 289 | pg_basebackup: write-ahead log end point: 0/5000158 |
| | 290 | pg_basebackup: waiting for background process to finish streaming ... |
| | 291 | pg_basebackup: syncing data to disk ... |
| | 292 | pg_basebackup: renaming backup_manifest.tmp to backup_manifest |
| | 293 | pg_basebackup: base backup completed |
| | 294 | |
| | 295 | }}} |
| | 296 | |
| | 297 | Опцијата -R автоматски креира standby.signal и primary_conninfo, со што PC серверот при следното стартување ќе работи како standby сервер и ќе се поврзе кон новиот primary. |
| | 298 | Потоа на PC се стартува PostgreSQL како replica: |
| | 299 | |
| | 300 | {{{ docker compose up -d }}} |
| | 301 | |
| | 302 | На PC може да се провери дали серверот е standby: |
| | 303 | {{{ |
| | 304 | film_rental=# SELECT pg_is_in_recovery(); |
| | 305 | pg_is_in_recovery |
| | 306 | ------------------- |
| | 307 | t |
| | 308 | (1 row) |
| | 309 | }}} |
| | 310 | |
| | 311 | На новиот primary сервер може да се провери дали PC серверот е поврзан како replica: |
| | 312 | {{{ |
| | 313 | film_rental=# SELECT client_addr, state, sync_state FROM pg_stat_replication; |
| | 314 | client_addr | state | sync_state |
| | 315 | ---------------+-----------+------------ |
| | 316 | 192.168.1.219 | streaming | async |
| | 317 | (1 row) |
| | 318 | }}} |
| | 319 | Со ова улогите се заменети: standby серверот е промовиран во нов primary сервер, а стариот primary сервер на PC е повторно иницијализиран како standby сервер. |
| | 320 | |
| | 321 | === Забелешка |
| | 322 | |
| | 323 | За стариот primary сервер на PC да може да стане replica, новиот primary сервер мора да дозволува replication конекции. Бидејќи по promotion standby серверот ја презема улогата на primary, неговиот pg_hba.conf станува активната конфигурација за контролирање на пристапот. |
| | 324 | |
| | 325 | Поради тоа, во pg_hba.conf на новиот primary сервер се додава правило кое дозволува replication конекција од PC: |
| | 326 | |
| | 327 | {{{ |
| | 328 | host replication replicator 192.168.1.219/32 scram-sha-256 |
| | 329 | }}} |
| | 330 | |
| | 331 | Ова правило значи дека корисникот replicator може да се поврзе за replication од IP адресата на PC серверот 192.168.1.219, користејќи password authentication со scram-sha-256. |
| | 332 | |
| | 333 | По измената на pg_hba.conf конфигурацијата се извршува reload: |
| | 334 | |
| | 335 | {{{ |
| | 336 | SELECT pg_reload_conf(); |
| | 337 | }}} |
| | 338 | |
| | 339 | Доколку ова правило не постои, pg_basebackup од PC кон новиот primary сервер не може да се изврши и PostgreSQL враќа грешка дека нема соодветен pg_hba.conf entry за replication конекцијата. |
| | 340 | |
| | 341 | |
| | 342 | |
| | 343 | |
| | 344 | |
| | 345 | |