Перейти к основному содержимому

Фоновый процесс автоочистки

Постоянное повторное выполнение команды 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 + DELETEautovacuum_vacuum_threshold 50 записейautovacuum_vacuum_scale_factor 0.2 (20% общего числа записей таблицы)
Очистка, VACUUM INSERTautovacuum_vacuum_insert_threshold 1000 записейautovacuum_vacuum_insert_scale_factor 0.2 (20% таблицы)
Обновление статистики, ANALYZE UPDATE + DELETE + INSERTautovacuum_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Накопленная стоимость операций, после которой выдерживается пауза-1vacuum_cost_limit
autovacuum_vacuum_cost_delayПродолжительность паузы после обработки очередной порции данных2msvacuum_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 будет выделяться каждому из процессов. Этот объем между процессами не делится, поэтому на сервере может вырасти использование памяти.