Уровень 3.0
Предусловия:
- Изучена лекция 8 «Журнал предзаписи»
Анализ ведения журнала предзаписи
-
Откройте терминал и подключитесь в psql к базе данных
postgresc рольюpostgres:[student@pkles-gt0040964 ~]$ sudo -iu postgres-bash-4.4$ psqlpsql (15.5)Введите "help", чтобы получить справку. -
Создайте базу данных
wal_dbи подключитесь к ней:postgres=# CREATE DATABASE wal_db;CREATE DATABASEpostgres=# \c wal_dbВы подключены к базе данных "wal_db" как пользователь "postgres". -
Создайте расширение
pageinspect:wal_db=# CREATE EXTENSION pageinspect;CREATE EXTENSIONВспомним, что расширение
pageinspectпозволяет посмотреть содержимое страниц данных. -
Создайте расширение
pg_walinspect:wal_db=# CREATE EXTENSION pg_walinspect;CREATE EXTENSIONРасширение
pg_walinspectпозволяет посмотреть содержимое записей WAL. -
Создайте таблицу
some_table:wal_db=# CREATE TABLE some_table(id integer, value integer) WITH (autovacuum_enabled=false);CREATE TABLEТаблица создана с параметром хранения
autovacuum_enabled = false, чтобы автоочистка не мешала проведению эксперимента.
Операции в журнале на уровне minimal
-
Проверьте уровень журнала предзаписи:
wal_db=# SHOW wal_level;wal_level-----------replica(1 строка)Уровень журнала предзаписи по умолчанию
replica. -
Измените значения параметров
max_wal_sendersиwal_level:wal_db=# ALTER SYSTEM SET max_wal_senders = 0;ALTER SYSTEMwal_db=# ALTER SYSTEM SET wal_level = minimal;ALTER SYSTEMПри установке значения параметра
wal_levelвminimalтакже было сброшено в 0 значение параметраmax_wal_senders. Это потребовалось, поскольку на уровнеminimalжурнал не может использоваться для потоковой репликации, то есть не может использоваться процессамиwalsender. -
Перезапустите экземпляр Pangolin и проверьте значения установленных параметров:
wal_db=# \q-bash-4.4$ pg_ctl restart -l logfileожидание завершения работы сервера.... готовосервер остановленожидание запуска сервера.... готовосервер запущен-bash-4.4$ psql -d wal_dbpsql (15.5)Введите "help", чтобы получить справку.wal_db=# SELECT name, setting FROM pg_settings WHERE name IN ('wal_level', 'max_wal_senders');name | setting-----------------+---------max_wal_senders | 0wal_level | minimal(2 строки)Перезапуск экземпляра потребовался для применения установленных значений параметров.
-
Сохраните в переменной
psqlпозицию вставки журнала WAL:wal_db=# SELECT pg_current_wal_insert_lsn() AS before_insert_lsn \gsetwal_db=# \echo :before_insert_lsn0/2119058Вспомним, что эта позиция вставки указывает на
LSNзаписи, следующей за последней вставленной в журнал WAL.Следующая запись WAL будет вставлена именно на эту позицию.
-
Вставьте одну строку в таблицу и посмотрите, как изменилась позиция вставки:
wal_db=# INSERT INTO some_table VALUES (1, 100);INSERT 0 1wal_db=# SELECT pg_current_wal_insert_lsn() AS after_insert_lsn \gsetwal_db=# \echo :after_insert_lsn0/2119208Позиция вставки увеличилась.
-
Узнайте размер записей WAL между сохраненными
LSN:wal_db=# SELECT pg_size_pretty(:'after_insert_lsn'::pg_lsn - :'before_insert_lsn'::pg_lsn);pg_size_pretty----------------432 bytes(1 строка)Вычитая значения типа
pg_lsn, можно получить размер записей WAL между ними.В данном случае были сгенерированы записи WAL общим размером 432 байта.
При этом в указанных записях должны присутствовать записи для операции вставки и фиксации транзакции (фиксация была выполнена неявно).
Однако в указанный интервал могли также попасть и записи для других операций.
Вспомним, что журнал WAL общий для всего кластера баз данных.
-
Посмотрите содержимое заголовков сгенерированных записей WAL:
wal_db=# SELECT start_lsn, resource_manager, record_type, record_length, block_ref FROM pg_get_wal_records_info(:'before_insert_lsn', :'after_insert_lsn');start_lsn | resource_manager | record_type | record_length | block_ref-----------+------------------+-------------------+---------------+-------------------------------------------------0/2119058 | XLOG | CHECKPOINT_ONLINE | 148 |0/21190F0 | Heap | INSERT+INIT | 81 | blkref #0: rel 1663/16390/16457 fork main blk 00/2119148 | Transaction | COMMIT | 36 |0/2119170 | XLOG | CHECKPOINT_ONLINE | 148 |(4 строки)Для просмотра заголовков записей WAL была использована функция
pg_get_wal_records_infoиз расширенияpg_walinspect.Для операции вставки была создана запись с типом
INSERT+INIT.INITозначает, что для вставки также была создана новая табличная страница. Ссылка на нее имеется в полеblock_ref. Менеджер ресурсов для данной записи —Heap. Вспомним, что менеджер ресурсов отвечает за интерпретацию записей различных типов.Следом за записью, соответствующей вставке, сохранилась запись о фиксации транзакции. Менеджер ресурсов для этой записи
Transaction.Однако в журнале оказались еще две записи типа
CHECKPOINT_ONLINE. Это записи о выполнении контрольных точек процессомcheckpointer. Они необходимы для обеспечения возможности удаления старых уже ненужных для восстановления записей из журнала.Более подробно контрольные точки будут рассмотрены в следующей теме.
-
Посмотрите, какой сейчас
LSNв заголовке измененной табличной страницы:wal_db=# SELECT lsn FROM page_header(get_raw_page('some_table',0));lsn-----------0/2119148(1 строка)Вспомним, что для соблюдения порядка сброса на диск журнальных записей и измененных страниц в заголовке страницы сохраняется
LSNзаписи, следующей за записью, соответствующей последней изменившей страницу операции.Действительно, страницу последней изменила операция
INSERT+INIT.LSNследующей записи в журнале как раз0/2119148. -
Наконец, посмотрите, в какой файл-сегмент журнала WAL была вставлена первая запись:
wal_db=# SELECT * FROM pg_walfile_name_offset(:'before_insert_lsn');file_name | file_offset--------------------------+-------------000000010000000000000002 | 1151064(1 строка)Функция
pg_walfile_name_offsetпозволяет поLSNзаписи определить сегмент журнала, в котором она находится, а также смещение относительно начала сегмента.
Операции в журнале на уровне replica
- Сбросьте значения конфигурационных параметров
wal_levelиmax_wal_senders:
wal_db=# ALTER SYSTEM RESET wal_level;
ALTER SYSTEM
wal_db=# ALTER SYSTEM RESET max_wal_senders;
ALTER SYSTEM
Вспомним, что параметр wal_level по умолчанию принимает значение replica.
-
Перезапустите экземпляр Pangolin и проверьте значения сброшенных параметров:
wal_db=# \q-bash-4.4$ pg_ctl restart -l logfileожидание завершения работы сервера.... готовосервер остановленожидание запуска сервера.... готовосервер запущен-bash-4.4$ psql -d wal_dbpsql (15.5)Введите "help", чтобы получить справку.wal_db=# SELECT name, setting FROM pg_settings WHERE name IN ('wal_level', 'max_wal_senders');name | setting-----------------+---------max_wal_senders | 10wal_level | replica(2 строки) -
Начните транзакцию и сохраните в переменную
psqlпозицию вставки журнала WAL:wal_db=# BEGIN;BEGINwal_db=*# SELECT pg_current_wal_insert_lsn() AS before_insert_lsn \gsetwal_db=*# \echo :before_insert_lsn0/2149A80 -
Очистите таблицу
some_tableкомандойTRUNCATE, вставьте в нее строку и обновите ее:wal_db=*# TRUNCATE some_table;TRUNCATE TABLEwal_db=*# INSERT INTO some_table VALUES (1, 100);INSERT 0 1wal_db=*# UPDATE some_table SET value = 150 WHERE id = 1;UPDATE 1 -
Сохраните в переменной новую позицию вставки:
wal_db=*# SELECT pg_current_wal_insert_lsn() AS after_insert_lsn \gsetwal_db=*# \echo :after_insert_lsn0/214DB28 -
Посмотрите содержимое заголовков сгенерированных записей WAL:
wal_db=*# SELECT start_lsn, resource_manager, record_type, record_length FROM pg_get_wal_records_info(:'before_insert_lsn', :'after_insert_lsn');start_lsn | resource_manager | record_type | record_length-----------+------------------+---------------+---------------0/2149A80 | Standby | RUNNING_XACTS | 680/2149AC8 | Standby | LOCK | 520/2149B00 | Storage | CREATE | 440/2149B30 | Heap | UPDATE | 1410/2149BC0 | XLOG | FPI_FOR_HINT | 25710/214A5E8 | Btree | INSERT_LEAF | 660/214A630 | XLOG | FPI_FOR_HINT | 67190/214C088 | Btree | INSERT_LEAF | 740/214C0D8 | Btree | INSERT_LEAF | 62830/214D968 | Standby | LOCK | 520/214D9A0 | Standby | RUNNING_XACTS | 760/214D9F0 | Heap | INSERT+INIT | 810/214DA48 | Heap | HOT_UPDATE | 850/214DAA0 | Standby | LOCK | 520/214DAD8 | Standby | RUNNING_XACTS | 76(15 строк)Вспомним, что на уровне журнала
replicaк перечню информации уровняminimalтакже добавляется информация об операциях массовой вставки, исключительных блокировках и статусах транзакций.В данном эксперименте командой
TRUNCATEбыла наложена исключительная блокировка на таблицуsome_table.В результате в журнале появились записи менеджера ресурсов
StandbyтипаLOCKдля исключительной блокировки и типаRUNNING_XACTSдля статусов транзакций.Также обратите внимание, что для операции обновления была создана запись типа
HOT_UPDATE, что подтверждает применение оптимизации HOT при обновлении. Действительно, у таблицыsome_tableнет индексов, поэтому все внутристраничные обновления являются HOT-обновлениями.Записи вверху таблицы (до записи с типом
INSERT+INIT) во многом соответствуют изменениям в системном каталоге, вызванным операциейTRUNCATE.Среди них можно выделить записи с типом
INSERT_LEAFменеджера ресурсовBtree, относящиеся к созданию новых ключей в листовых узлах индекса. -
Откатите транзакцию:
wal_db=*# ROLLBACK;ROLLBACK
Сравнение синхронного и асинхронного режимов
-
Посмотрите значение параметра
synchronous_commit:wal_db=# SHOW synchronous_commit;synchronous_commit--------------------on(1 строка)По умолчанию журнальные записи сбрасываются в энергонезависимые накопители в синхронном режиме.
-
Откройте второй терминал и перейдите в режим выполнения команд от имени пользователя
postgres:[student@pkles-gt0041307 ~]$ sudo -iu postgres -
Во втором сеансе инициализируйте и выполните минутный тест
pgbench:-bash-4.4$ pgbench -i wal_dbdropping old tables...NOTICE: table "pgbench_accounts" does not exist, skippingNOTICE: table "pgbench_branches" does not exist, skippingNOTICE: table "pgbench_history" does not exist, skippingNOTICE: table "pgbench_tellers" does not exist, skippingcreating tables...generating data (client-side)...100000 of 100000 tuples (100%) done (elapsed 0.01 s, remaining 0.00 s)vacuuming...creating primary keys...done in 0.23 s (drop tables 0.00 s, create tables 0.01 s, client-side generate 0.13 s, vacuum 0.04 s, primary keys 0.05 s).-bash-4.4$ pgbench -T 60 wal_dbpgbench (15.5)starting vacuum...end.transaction type: <builtin: TPC-B (sort of)>scaling factor: 1query mode: simplenumber of clients: 1number of threads: 1maximum number of tries: 1duration: 60 snumber of transactions actually processed: 48757number of failed transactions: 0 (0.000%)latency average = 1.231 msinitial connection time = 4.175 mstps = 812.659751 (without initial connection time)При синхронной фиксации транзакций время отклика (
latency average) составило 1.231 ms, а скорость выполнения транзакцийtps= 812.659751. -
В первом сеансе выключите синхронный режим фиксации транзакций:
wal_db=# ALTER SYSTEM SET synchronous_commit = off;ALTER SYSTEMwal_db=# SELECT pg_reload_conf();pg_reload_conf----------------t(1 строка)wal_db=# SHOW synchronous_commit;synchronous_commit--------------------off(1 строка) -
Во втором сеансе повторите тест
pgbench:-bash-4.4$ pgbench -T 60 wal_dbpgbench (15.5)starting vacuum...end.transaction type: <builtin: TPC-B (sort of)>scaling factor: 1query mode: simplenumber of clients: 1number of threads: 1maximum number of tries: 1duration: 60 snumber of transactions actually processed: 118888number of failed transactions: 0 (0.000%)latency average = 0.505 msinitial connection time = 3.580 mstps = 1981.565811 (without initial connection time)При асинхронной фиксации транзакций время отклика (
latency average) уменьшилось более чем в два раза и составило 0.505 ms, а скорость выполнения транзакций увеличилась более чем в два раза:tps= 1981.565811.На основании этого можно сделать вывод, что в OLTP-системах с большим количеством транзакций в единицу времени режим фиксации транзакций может существенно влиять на производительность системы.
В то же время стоит помнить, что в асинхронном режиме в случае сбоя часть последних зафиксированных изменений может быть потеряна.
Завершение
- В первом сеансе сбросьте значение параметра
synchronous_commit:
wal_db=# ALTER SYSTEM RESET synchronous_commit;
ALTER SYSTEM
wal_db=# SELECT pg_reload_conf();
pg_reload_conf
----------------
t
(1 строка)
wal_db=# SHOW synchronous_commit;
synchronous_commit
--------------------
on
(1 строка)
-
В первом сеансе подключитесь базе данных
postgres, удалите базу данныхwal_dbи выйдите из сеанса:wal_db=# \c postgresВы подключены к базе данных "postgres" как пользователь "postgres".postgres=# DROP DATABASE wal_db;DROP DATABASEpostgres=# \q
Самопроверка
Вопрос 1
Состояние журнала предзаписи за некоторый интервал LSN представлено ниже:
start_lsn | resource_manager | record_type
-----------+------------------+-------------
0/97933B8 | Heap | INSERT+INIT
0/9793410 | Heap | HOT_UPDATE
0/9793468 | Heap | INSERT
В заголовке табличной страницы значение поля pd_lsn = '0/9793410'.
Журнальная запись какого типа была сформирована в результате последнего изменения указанной табличной страницы?
Вопрос 2
В каталоге pg_wal находятся следующие сегменты журнала предзаписи:
name
--------------------------
000000010000000000000009
00000001000000000000000A
00000001000000000000000B
00000001000000000000000C
В каком из сегментов находится журнальная запись с LSN = '0/9B996AA'?
Вопрос 3
Состояние журнала предзаписи за некоторый интервал LSN представлено ниже:
start_lsn | resource_manager | record_type | record_length
-----------+------------------+---------------+---------------
0/9799650 | Heap | HOT_UPDATE | 85
0/97996A8 | Standby | RUNNING_XACTS | 76
0/97996F8 | Heap | INSERT | 65
0/9799740 | Standby | RUNNING_XACTS | 76
0/9799790 | Transaction | COMMIT | 36
К какому уровню (wal_level) может относиться журнал предзаписи с представленным состоянием? Выберите все верные варианты ответа:
Вопрос 4
Выберите все верные утверждения относительно асинхронного режима фиксации транзакций