Фоновый процесс автоочистки
Постоянное повторное выполнение команды VACUUM
по всем таблицам — не лучший способ обслуживать СУБД. Поэтому разработчики для текущего обслуживания объектов добавили в PostgreSQL набор фоновых процессов автоочистки.
Эти процессы запускаются при запуске сервера, когда установлен параметр autovacuum = on
. Запускается координатор (launcher) и максимум autovacuum_max_workers
обработчиков, каждый из которых для обслуживания выделенной ему таблицы подключается к одной из баз кластера. Если баз больше, чем обработчиков, то свободный обработчик будет переключаться на базу, в которой находится обслуживаемая таблица.
После запуска координатор постоянно пробуждается по таймеру, который настраивается параметром autovacuum_naptime
и составляет (autovacuum_naptime
/кол-во баз в кластере). По умолчанию autovacuum_naptime
установлен в 1 минуту, при 3 базах таймер будет установлен на 60 / 3 = 20 секунд.
Процесс автоочистки обслуживает только те таблицы, которые существенно изменились со времени последнего обслуживания. Для этого ему необходимы данные о количестве модификаций таблицы, которые собирает другой фоновый процесс — сборщик статистики. Чтобы эта информация непрерывно собиралась, должен быть включен параметр track_counts = on
. Без сборщика информации автоочистка не сможет выбирать среди таблиц кандидатуры для обработки.
Для автоочистки в СУБД Pangolin настраивается при установке объем буфера в памяти – параметр сервера autovacuum_work_mem
. При инсталляции параметр будет установлен в 1/48 от объема физической памяти сервера. Если параметр установить в -1, то будет использовано значение параметра maintenance_work_mem
.
Отладка процесса включается параметром log_autovacuum_min_duration
. Если автоочистка обрабатывает одну из таблиц дольше указанного времени, то в протокол сервера попадает подробная информация, которая помогает настроить параметры по реальной нагрузке.
На автоочистку возложены те же обязанности, что и на команду VACUUM
: очистка полностью устаревших версий записей в таблицах и индексах, заморозка записей «доисторических» транзакций, поддержка карт FSM и VM, обновление статистики ANALYZE, поддержка массива статусов clog в памяти и на диске.
Фоновый процесс автоочистки проверяет статистику баз и таблиц через заданный интервал времени и выдает процессам-обработчикам команды VACUUM
и ANALYZE
на таблицы.
Хотя сама автоочистка и запускается по таймеру, было бы неверно на каждый запуск повторять в нем очистку и обновление статистики при малейших изменениях данных. Чтобы избежать слишком частых обращений к таблице, настраиваются пороги минимального количества изменений со времени последней очистки, после которого таблица поступает на следующую очистку. Применяется одновременно абсолютный и относительный порог, который может быть настроен по VACUUM
и по ANALYZE
раздельно.
Из-за специфики MVCC, по VACUUM
пороги задаются отдельно для накопления изменений (UPDATE
+ DELETE
) и отдельно – для накопления INSERT
. Дело здесь в том, что таблица, по которой выполняются только INSERT
, формально вообще не нуж дается в очистке, поскольку не содержит ни одной устаревшей версии записей. Однако, она нуждается в заморозке даже больше остальных таблиц (все действующие записи должны быть заморожены рано или поздно). Поскольку автоматическая заморозка — часть VACUUM
/автоочистки, отдельно от очистки выполнить ее не получится – она выполняется в процессе автоочистки. Только не с каждой очисткой, а несколько реже.
Параметры сервера
Автоматическая операция — характер изменений таблицы | Абсолютный порог — значение по умолчанию | Относительный порог, доля от таблицы — значение по умолчанию |
---|---|---|
Очистка, VACUUM UPDATE + DELETE | autovacuum_vacuum_threshold 50 записей | autovacuum_vacuum_scale_factor 0.2 (20% общего числа записей таблицы) |
Очистка, VACUUM INSERT | autovacuum_vacuum_insert_threshold 1000 записей | autovacuum_vacuum_insert_scale_factor 0.2 (20% таблицы) |
Обновление статистики, ANALYZE UPDATE + DELETE + INSERT | autovacuum_analyze_threshold 50 записей | autovacuum_analyze_scale_factor 0.1 (10% таблицы) |
Например, таблицу из 500 записей настроенная по умолчанию автоочис тка сможет выбрать для:
- очистки,
VACUUM
: при изменении от 50 + 0.2 * 500 = 150 записей или при добавлении от 1000 + 0.2 * 500 = 1100 записей; - обновления статистики,
ANALYZE
: при изменении или добавлении от 50 + 0.1 * 500 = 100 записей.
Эти параметры могут быть настроены только на уровне сервера (postgresql.conf
для одиночного сервера, DCS и postgres.yml
— для кластера). Применяются для всех баз кластера. Однако, возможна их тонкая настройка для каждой из таблиц. Подробное описание в разделе «Настройки и правила перекрытия параметров».
Просмотреть счетчики модификаций таблиц с момента запуска сервера или сброса статистики можно так:
SELECT n_tup_ins as "inserts",n_tup_upd as "updates",n_tup_del as "deletes", n_live_tup as "live_tuples", n_dead_tup as "dead_tuples" FROM pg_stat_user_tables
WHERE schemaname = 'sch1';
Для небольших, часто изменяемых таблиц целесообразно установить более высокий абсолютный порог и поднять относительный, чтобы не повторять очистку и сбор статистики слишком часто. А для объемных, редко модифицируемых — отказаться от относительного порога (обнулить его), использовать только абсолютный порог порядка нескольких сотен тысяч записей.
Если бы автоматическая очистка выполнялась только по порогам количества модификаций, то в некоторых таблицах после завершения фазы активных изменений могли бы накопиться версии записей, относящиеся к очень старым, но еще не замороженным транзакциям. Содержание таких версий в таблице не позволяло бы освободить идентификаторы транзакций или мультитранзакций, могло бы повлечь «раздувание» массивов clog/multixact и постепенно приве сти к обороту счетчика. Подобные инциденты предотвращает автоматическая заморозка для предотвращения зацикливания, рассматриваемая в разделе «Автоочистка для предотвращения зацикливания счетчиков». В этом же разделе подробно описаны параметры autovacuum_freeze_max_age
, autovacuum_multixact_freeze_max_age
– пороги этой заморозки).
Блокировки во время автоочистки
На уровне таблицы и страниц объектов блокировки автоочистки – как у VACUUM
без ключа FULL
.
Есть одно важное отличие от VACUUM
: автоочистка автоматически предотвращает инциденты по исключительной блокировке таблицы. Для этого процессы автоочистки непрерывно проверяют, не оказались ли они причиной блокировки любой из пользовательских сессий. Если за ними занял очередь на блокировке хотя бы один процесс, то автоочистки по заблокированной таблице немедленно отменяется. Побочный эффект: приложение, постоянно выполняющее DDL между блоками транзакционной нагрузки, может постоянно прерывать автоочистку до завершения обработки затронутых DDL таблиц.
«Вежливый» режим автоочистки
Фоновую очистку почти всегда необходимо выполнять так, чтобы она периодически приостанавливалась, пропуская пользовательские сессии к физическим ресурсам.
Здесь «вежливый» режим работает так же, как редко применяемый «вежливый» режим команды VACUUM
. Он использует те же баллы относительной стоимости операций обработки блока vacuum_cost_page_hit
, vacuum_cost_page_miss
и vacuum_cost_page_dirty
что указаны в таблице параметров.
Объем порции и пауза после ее обработки могут быть настроены для VACUUM
и автоочистки как раздельно, так и одновременно. Параметры:
Параметр | Назначение | По умолчанию | Значение при -1 |
---|---|---|---|
autovacuum_vacuum_cost_limit | Накопленная стоимость операций, после которой выдерживается пауза | -1 | vacuum_cost_limit |
autovacuum_vacuum_cost_delay | Продолжительность паузы после обработки очередной порции данных | 2ms | vacuum_cost_delay |
Здесь, если параметр автоочистки установлен в значение -1, то в качестве его значения применяется соответствующий параметр VACUUM
из столбца Значение при -1.
«Вежливый» режим — это постоянный, ожидаемый режим для автоматической очистки.
Скорость автоматической очистки по умолчанию при обработке таблицы в памяти — до 781 МБ/с, при чтении с диска — до 78.1 МБ/с, при изменении данных — до 39 МБ/с (расчеты - в том же описании для VACUUM. Часто полностью кешированная таблица обслуживается очень быстро, а вот скорость обработки значительно измененной таблицы на диске оставляет желать лучшего. Если это так, лучше пересмотреть баллы стоимости операций и/или размер порции по фактической пропускной способности диска. Настройки по умолчанию лучше описывают шпиндельные HDD, а на SSD или Flash стоит понизить стоимости page_miss
и page_dirty
минимум в 2-3 раза и/или увеличить порцию, например, до размера физической страницы контроллера памяти.
Особенность параллельной «вежливой» автоочистки
Когда запущено несколько параллельных обработчиков автоочистки, стоимость порции операций autovacuum_vacuum_cost_limit
распределяется пропорционально среди всех работающих процессов. Сумма ограничений всех процессов не превосходит заданный предел. А вот паузы cost_delay
действуют в каждом процессе без изменений. Поэтому после увеличения мощности автоочистки с повышением параметра autovacuum_max_workers
можно получить парадоксальную ситуацию: обработчиков запущено больше и все они активны, но большие таблицы обрабатываются существенно дольше.
Дело в том, что автоочистка при увеличении количества процессов кратно понижает скорость каждого из них, а таблицы между потоками не передаются.
Чтобы получить ожидаемое поведение, следует пропорционально увеличивать autovacuum_vacuum_cost_limit
вслед за autovacuum_max_workers
.
При увеличении autovacuum_max_workers
следует учесть, что буфер в памяти размером autovacuum_work_mem
будет выделяться каждому из процессов. Этот объем между процессами не делится, поэтому на сервере может вырасти использование памяти.