Журнал

Создадим небольшую таблицу:

=> CREATE DATABASE wal_log;
CREATE DATABASE
=> \c wal_log
You are now connected to database "wal_log" as user "postgres".
=> CREATE TABLE t(id integer);
CREATE TABLE
=> INSERT INTO t VALUES (1);
INSERT 0 1

Мы будем заглядывать в заголовок табличной страницы. Для этого понадобится расширение:

=> CREATE EXTENSION pageinspect;
CREATE EXTENSION

Начнем транзакцию.

=> BEGIN;
BEGIN

Текущая позиция в журнале:

=> SELECT pg_current_wal_insert_lsn();
 pg_current_wal_insert_lsn 
---------------------------
 0/1C349E8
(1 row)

LSN выводится как два 32-битных числа в шестнадцатеричной системе через косую черту.


Эта позиция соответствует файлу:

=> SELECT pg_walfile_name('0/1C349E8');
     pg_walfile_name      
--------------------------
 000000010000000000000001
(1 row)

Имя файла состоит из трех чисел. Первое - номер ветви времени (используется при восстановлении из архива), а два следующих - старшие разряды LSN.


Все журнальные файлы находятся в каталоге /usr/local/pgsql/data/pg_wal/, а в PostgreSQL 10 их также можно увидеть специальной функцией:

=> SELECT * FROM pg_ls_waldir() LIMIT 10;
           name           |   size   |      modification      
--------------------------+----------+------------------------
 000000010000000000000001 | 16777216 | 2019-08-12 17:15:46+03
(1 row)


Изменим строку в таблице:

=> UPDATE t SET id = id + 1;
UPDATE 1

Позиция в журнале изменилась:

=> SELECT pg_current_wal_insert_lsn();
 pg_current_wal_insert_lsn 
---------------------------
 0/1C34A30
(1 row)


Этот же номер LSN (или меньший, если в журнал попали дополнительные записи) мы найдем и в заголовке измененной страницы:

=> SELECT lsn FROM page_header(get_raw_page('t',0));
    lsn    
-----------
 0/1C34A30
(1 row)


Завершим транзакцию.

=> COMMIT;
COMMIT

Позиция в журнале снова изменилась:

=> SELECT pg_current_wal_insert_lsn();
 pg_current_wal_insert_lsn 
---------------------------
 0/1C34A54
(1 row)


Размер журнальных записей (в байтах), соответствующих нашей транзакции, можно узнать вычитанием одной позиции из другой:

=> SELECT '0/1C34A54'::pg_lsn - '0/1C349E8'::pg_lsn;
 ?column? 
----------
      108
(1 row)

Безусловно, в журнал попадает информация обо всех действиях во всем кластере, но в данном случае мы рассчитываем на то, что в системе ничего не происходит.


Теперь воспользуемся утилитой pg_waldump, чтобы посмотреть содержимое журнала.

Список менеджеров ресурсов:

student$ pg_waldump -r list
XLOG
Transaction
Storage
CLOG
Database
Tablespace
MultiXact
RelMap
Standby
Heap2
Heap
Btree
Hash
Gin
Gist
Sequence
SPGist
BRIN
CommitTs
ReplicationOrigin
Generic
LogicalMessage

Утилита может работать и с диапазоном LSN (как в этом примере), и выбрать записи для указанной транзакции. Запускать ее следует от имени пользователя ОС postgres, так как ей требуется доступ к журнальным файлам на диске.

postgres$ pg_waldump -p /usr/local/pgsql/data/pg_wal -s 0/1C349E8 -e 0/1C34A54 000000010000000000000001
rmgr: Heap        len (rec/tot):     69/    69, tx:        670, lsn: 0/01C349E8, prev 0/01C344B0, desc: HOT_UPDATE off 1 xmax 670 ; new off 2 xmax 0, blkref #0: rel 1663/16625/16626 blk 0
rmgr: Transaction len (rec/tot):     34/    34, tx:        670, lsn: 0/01C34A30, prev 0/01C349E8, desc: COMMIT 2019-08-12 17:15:46.557989 MSK

Мы видим заголовки журнальных записей:


Конец демонстрации.