Заглянем в управляющий файл /usr/local/pgsql/data/global/pg_control. Это можно сделать с помощью утилиты pg_controldata.
postgres$ pg_controldata
pg_control version number: 1002 Catalog version number: 201707211 Database system identifier: 6724283719152707292 Database cluster state: in production pg_control last modified: Пн 12 авг 2019 17:15:45 Latest checkpoint location: 0/1BF5734 Prior checkpoint location: 0/1BF5668 Latest checkpoint's REDO location: 0/1BF56FC Latest checkpoint's REDO WAL file: 000000010000000000000001 Latest checkpoint's TimeLineID: 1 Latest checkpoint's PrevTimeLineID: 1 Latest checkpoint's full_page_writes: on Latest checkpoint's NextXID: 0:667 Latest checkpoint's NextOID: 24817 Latest checkpoint's NextMultiXactId: 1 Latest checkpoint's NextMultiOffset: 0 Latest checkpoint's oldestXID: 548 Latest checkpoint's oldestXID's DB: 1 Latest checkpoint's oldestActiveXID: 666 Latest checkpoint's oldestMultiXid: 1 Latest checkpoint's oldestMulti's DB: 1 Latest checkpoint's oldestCommitTsXid:0 Latest checkpoint's newestCommitTsXid:0 Time of latest checkpoint: Пн 12 авг 2019 17:15:45 Fake LSN counter for unlogged rels: 0/1 Minimum recovery ending location: 0/0 Min recovery ending loc's timeline: 0 Backup start location: 0/0 Backup end location: 0/0 End-of-backup record required: no wal_level setting: replica wal_log_hints setting: off max_connections setting: 100 max_worker_processes setting: 8 max_prepared_xacts setting: 0 max_locks_per_xact setting: 64 track_commit_timestamp setting: off Maximum data alignment: 4 Database block size: 8192 Blocks per segment of large relation: 131072 WAL block size: 8192 Bytes per WAL segment: 16777216 Maximum length of identifiers: 64 Maximum columns in an index: 32 Maximum size of a TOAST chunk: 2000 Size of a large-object chunk: 2048 Date/time type storage: 64-bit integers Float4 argument passing: by value Float8 argument passing: by reference Data page checksum version: 1 Mock authentication nonce: f6a300dfc223e2b1ea9239f32ab1de58482237576b9bdb4e17a53f779a59dc9e
Видим много справочной информации, из которой особый интерес представляют данные о последней контрольной точке и статус кластера: "in production".
Выполним вручную контрольную точку и посмотрим, как это отражается в журнале и в управляющем файле.
=> SELECT pg_current_wal_insert_lsn();
pg_current_wal_insert_lsn --------------------------- 0/1C34A54 (1 row)
=> SELECT pg_walfile_name('0/1C34A54');
pg_walfile_name -------------------------- 000000010000000000000001 (1 row)
=> CHECKPOINT;
CHECKPOINT
=> SELECT pg_current_wal_insert_lsn();
pg_current_wal_insert_lsn --------------------------- 0/1C34AF0 (1 row)
В журнал попадает запись о том, что контрольная точка пройдена:
postgres$ pg_waldump -p /usr/local/pgsql/data/pg_wal -s 0/1C34A54 -e 0/1C34AF0 000000010000000000000001
rmgr: Standby len (rec/tot): 50/ 50, tx: 0, lsn: 0/01C34A54, prev 0/01C34A30, desc: RUNNING_XACTS nextXid 671 latestCompletedXid 670 oldestRunningXid 671 rmgr: XLOG len (rec/tot): 102/ 102, tx: 0, lsn: 0/01C34A88, prev 0/01C34A54, desc: CHECKPOINT_ONLINE redo 0/1C34A54; tli 1; prev tli 1; fpw true; xid 0:671; oid 24817; multi 1; offset 0; oldest xid 548 in DB 1; oldest multi 1 in DB 1; oldest/newest commit timestamp xid: 0/0; oldest running xid 671; online
В описании записи указан LSN начала контрольной точки (redo).
Сравним с данными управляющего файла:
postgres$ pg_controldata | egrep 'Latest.*location'
Latest checkpoint location: 0/1C34A88 Latest checkpoint's REDO location: 0/1C34A54
Данные о LSN, очевидно, совпадают.
Теперь сымитируем сбой, принудительно выключив сервер.
=> CREATE DATABASE wal_checkpoint;
CREATE DATABASE
=> \c wal_checkpoint
You are now connected to database "wal_checkpoint" as user "postgres".
=> CREATE TABLE test(t text);
CREATE TABLE
=> INSERT INTO test VALUES ('Перед сбоем');
INSERT 0 1
=> \q
postgres$ pg_ctl -w -D /usr/local/pgsql/data stop -m immediate
waiting for server to shut down.... done server stopped
Сейчас на диске находятся журнальные записи, но табличные страницы не были сброшены на диск.
Проверим состояние кластера:
postgres$ pg_controldata | grep state
Database cluster state: in production
Состояние не изменилось. При запуске PostgreSQL поймет, что произошел сбой и требуется восстановление.
postgres$ pg_ctl -w -l /home/postgres/logfile -D /usr/local/pgsql/data start
waiting for server to start.... done server started
postgres$ tail -n 7 /home/postgres/logfile
2019-08-12 17:15:48.053 MSK [10010] LOG: database system was interrupted; last known up at 2019-08-12 17:15:47 MSK 2019-08-12 17:15:48.841 MSK [10010] LOG: database system was not properly shut down; automatic recovery in progress 2019-08-12 17:15:48.845 MSK [10010] LOG: redo starts at 0/1C35C78 2019-08-12 17:15:48.846 MSK [10010] LOG: invalid record length at 0/1C59A00: wanted 24, got 0 2019-08-12 17:15:48.846 MSK [10010] LOG: redo done at 0/1C599DC 2019-08-12 17:15:48.846 MSK [10010] LOG: last completed transaction was at log time 2019-08-12 17:15:47.80934+03 2019-08-12 17:15:48.880 MSK [10009] LOG: database system is ready to accept connections
student$ psql wal_checkpoint
=> SELECT * FROM test;
t ------------- Перед сбоем (1 row)
Как видим, таблица и данные восстановлены.
Теперь остановим экземпляр штатным способом:
=> \q
postgres$ pg_ctl -w -D /usr/local/pgsql/data stop
waiting for server to shut down.... done server stopped
При такой остановке PostgreSQL выполняет контрольную точку, чтобы сбросить на диск все данные.
Проверим состояние кластера:
postgres$ pg_controldata | grep state
Database cluster state: shut down
Теперь состояние - "shut down", что соответствует корректной остановке.
Снова запустим экземпляр.
postgres$ pg_ctl -w -l /home/postgres/logfile -D /usr/local/pgsql/data start
waiting for server to start.... done server started
student$ psql wal_checkpoint
Параметр checkpoint_warning выводит предупреждение, если контрольные точки, вызванные переполнением размера журнальных файлов, выполняются слишком часто. Его значение по умолчанию:
=> SHOW checkpoint_warning;
checkpoint_warning -------------------- 30s (1 row)
Его следует привести в соответствие со значением checkpoint_timeout.
Параметр log_checkpoints позволяет получать в журнале сообщений сервера информацию о выполняемых контрольных точках. По умолчанию параметр выключен:
=> SHOW log_checkpoints;
log_checkpoints ----------------- off (1 row)
Включим его.
=> ALTER SYSTEM SET log_checkpoints = on;
ALTER SYSTEM
=> SELECT pg_reload_conf();
pg_reload_conf ---------------- t (1 row)
Теперь запишем что-нибудь в таблицу и выполним контрольную точку.
=> INSERT INTO test SELECT g.id::text FROM generate_series(1,100000) AS g(id);
INSERT 0 100000
=> CHECKPOINT;
CHECKPOINT
Вот какую информацию можно будет узнать из журнала сообщений:
postgres$ tail -n 2 /home/postgres/logfile
2019-08-12 17:15:49.761 MSK [10148] LOG: checkpoint starting: immediate force wait 2019-08-12 17:15:49.791 MSK [10148] LOG: checkpoint complete: wrote 442 buffers (2.7%); 0 WAL file(s) added, 0 removed, 0 recycled; write=0.004 s, sync=0.017 s, total=0.030 s; sync files=2, longest=0.015 s, average=0.008 s; distance=6226 kB, estimate=6226 kB
Статистика работы процессов контрольной точки и фоновой записи отражается в одном общем представлении (раньше обе задачи решались одним процессом; затем их функции разделили, но представление осталось).
=> SELECT * FROM pg_stat_bgwriter \gx
-[ RECORD 1 ]---------+------------------------------ checkpoints_timed | 0 checkpoints_req | 1 checkpoint_write_time | 4 checkpoint_sync_time | 17 buffers_checkpoint | 442 buffers_clean | 0 maxwritten_clean | 0 buffers_backend | 444 buffers_backend_fsync | 0 buffers_alloc | 630 stats_reset | 2019-08-12 17:15:48.881345+03
* checkpoints_timed - контрольные точки по расписанию (checkpoint_timeout);
* checkpoints_req - контрольные точки по требованию (max_wal_size);
* buffers_checkpoint - страницы, сброшенные при контрольных точках;
* buffers_backend - страницы, сброшенные обслуживающими процессами;
* buffers_clean - страницы, сброшенные процессом фоновой записи;
В хорошо настроенной системе значение buffers_backend должно быть существенно меньше, чем сумма buffers_checkpoint и buffers_clean.
Большое значение checkpoint_req (по сравнению с checkpoints_timed) говорит о том, что контрольные точки происходят чаще, чем предполагалось.
Конец демонстрации.