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

Общие объекты и параметры для всех видов очистки

Массив статусов транзакций clog или xact

Как отмечалось ранее, снимки операций включают списки транзакций по состоянию на момент старта операции. Для оперативного составления списка и вычисления правил видимости версий записей используется отдельный массив статусов транзакций.

В разделяемой памяти сервера организована структура, называемая Commit Log или clog. Это массив, индексом которого служит номер транзакции, а элементы хранят один из четырех статусов: в процессе, зафиксирована, отменена или «порция зафиксирована» (только для подтранзакций между точками сохранения основной транзакции).

Массив фиксируется на диске во время контрольных точек и штатного закрытия сервера в поддиректории кластера баз pg_xact.

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

Зафиксированные на диске данные массива защищены журналом WAL и сохраняются в резервных копиях. При физическом восстановлении сервера clog должен быть полностью восстановлен из копии и обновлен по журналам транзакций (обычно это происходит автоматически).

На диске массив статусов хранится в виде нескольких файлов фиксированного размера. Файлы автоматически добавляются при нарастании списка активных транзакций в памяти. Обслуживание заключается в периодической очистке устаревшей части информации в памяти и удалении соответствующих неактуальных файлов с диска.

Карта видимости таблицы

Постоянное полное сканирование таблиц и индексов при периодической очистке устаревших версий и при каждой «заморозке» (переносе неактивных транзакций в архив) – не лучшее применение ресурсов сервера.

Чтобы во время очистки не повторять уже проделанные операции, процессы очистки запоминают состояние полностью обработанных блоков таблицы. Для этого служит хранимый на диске при файлах таблицы «слой» (отдельный набор файлов) – карта видимости (visibility map). В этих файлах на каждый 8КБ блок таблицы хранится два бита:

  • первый при очистке блока выставляется в 1, если все версии строк в блоке - действующие (видимые), или в 0, если в блоке есть хотя бы одна версия, срок действия которой завершен (эту версию сразу удалять нельзя – выше описано, почему);
  • второй при «заморозке» выставляется в 1, если все версии строк в блоке «заморожены» (открывшие их транзакции ушли в историю), иначе - в 0.

Во время очистки нет смысла просматривать блоки таблицы, в которых все версии записей действительны, поэтому очистка может пропустить блоки, для которых бит видимости выставлен в 1.

Точно так же блоки, в которых все записи уже «заморожены», можно пропускать при «заморозке».

Таблица изначально создается без карты видимости. Создают карту процессы очистки и они же выставляют в 1 биты статуса при очистке/заморозке блоков. А вот сбросить биты может любая из транзакций, иначе очистка пропускала бы недавно измененные блоки.

У индексов нет карты видимости, потому что в них видимость версий записей не отмечается.

Карта свободного пространства

В карте свободного пространства записано, сколько свободного места имеется в каждом из блоков таблицы или индекса для изменения и добавления записей. Она напоминает по структуре индекс (двоичное дерево), в котором каждому из 8КБ блоков объекта выделен 1 байт. В байте записана доля свободного места в блоке в баллах от 0 до 255. Двоичное дерево, похожее на индекс, построено на этом значении как на ключе и позволяет сессиям быстро находить блоки с заказанным минимальным количеством свободного места либо убеждаться, что таких блоков не осталось – придется расширять объект.

Физически карта хранится как отдельный файл (слой) при наборе файлов таблицы/индекса.

Картой пользуется каждая из сессий во время добавления и изменения записей: ищет свободный блок, обновляет карту после внесения изменений.

Карта активно пополняется при очистке объекта в процессе высвобождения пространства в блоках.

Фактор заполнения

При изменении данных в таблицах и индексах выгодно использовать свободное место в блоке, чтобы избежать операций расширения объекта и разделения блоков.

Параметр fillfactor в описании таблицы и индекса задает фактор заполнения в процентах, от 10 до 100. Значение по умолчанию — 100 (плотное заполнение) для таблицы и 90 (почти полное заполнение) - для индекса.

При меньшем факторе заполнения операции INSERT упаковывают данные в страницы только до заданного процента, а оставшееся место резервируется для изменения строк на этой же странице. В результате UPDATE получает шанс поместить измененную копию строки в ту же страницу, откуда извлечена исходная копия. Это гораздо эффективнее, чем размещать копию на другой странице. Также, свободное пространство в блоке может использоваться для внутристраничных обновлений полей таблицы, не входящих в индексы (так называемых HOT update).

Для активно изменяемых таблиц и индексов стоит выбрать меньший фактор заполнения, чтобы зарезервировать больше пространства для изменений. Можно начать с 85..90%. При меньших значениях (больше свободного места), скорее всего, дополнительное свободное место не добавит производительности.

Нет глобального параметра fillfactor на уровне сервера/базы/схемы. Можно изменять только настройки объектов по одному. Изменения не применяются к существующим блокам. Чтобы переупаковать данные, потребуется выполнить VACUUM FULL или CLUSTER. Либо воспользоваться pg_repack/pg_squeeze.

Особенности Pangolin: дисциплина организации доступных блоков

В Pangolin, как и в PostgreSQL, нет списка свободных блоков объекта. Т.е. не поддерживается знакомая по Oracle до 10g дисциплина списка свободных блоков Freelists. Соответственно и аналога параметра PCTUSED тоже нет. Единственная доступная дисциплина - карта доступных блоков, аналог битовой карты из новой для Oracle дисциплины ASSM.

Параметр fillfactor примерно соответствует (PCTFREE - 100%) из Oracle.

Списка интересующихся транзакций (ITL) по каждому блоку в Pangolin тоже нет, поэтому нет и параметров объекта, которые напоминали бы INITRANS и MAXTRANS. Поддержка цепочек транзакций, конкурирующих за одну и ту же запись, возложена на общий для кластера системный объект - список мультитранзакций, который также требует периодического обслуживания.