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

pg_freeze_recovery. Ручная коррекция работы VACUUM

В исходном дистрибутиве установлено по умолчанию: нет.

Связанные компоненты: отсутствуют.

Схема размещения: ext.

Расширение считается устаревшим, рекомендуется использовать pg_surgery.

Модуль pg_freeze_recovery предоставляет функцию для ручной коррекции работы VACUUM. Расширение предназначено для исправления ситуации вида:

vacuumdb: error: processing of database "stmnt3_sh1" failed: ERROR: found xmin 1287773215 from before relfrozenxid 1296057024
CONTEXT: while scanning block 313483885

В расширении предусмотрена функция freeze_page(regclass, tid). Для использования в скрипте вызов производится следующим образом:

SELECT freeze_page('table1','(5405,188)');

На вход подается имя таблицы, идентификатор записи (tid): номер страницы и смещение на странице записи. Для использования расширения pg_freeze_recovery необходимо наличие в БД предварительно установленного расширения pageinspect. Предполагается, что pg_freeze_recovery корректно работает с wal - выполняется запись и смещение LSN вперед.

Крайне рекомендуется во время использования pg_freeze_recovery отключать автоочистку:

ALTER SYSTEM SET autovacuum = off;

Доработка

Доработка не проводилась.

Ограничения

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

Установка

При наличии прав администратора СУБД включение модуля выполняется запросом:

CREATE EXTENSION pg_freeze_recovery SCHEMA ext;

Настройка

Настройка не требуется.

Использование модуля

VACUUM -a -F

Пример вывода результата запроса:

vacuumdb: vacuuming database "db0"
vacuumdb: error: processing of database "db0" failed ERROR: found xmin 727 from before relfrozenxid 743
CONTEXT: while scanning block 0 offset 2 of relation "pg_catalog.pg_shdescription"

Вывод показывает наличие незамороженных строк до горизонта заморозки (743). Горизонт заморозки также можно получить запросом:

SELECT relfrozenxid FROM pg_class WHERE oid = 'pg_catalog.pg_shdescription'::regclass;

Пример вывода результата запроса:

 relfrozenxid
--------------
512
(1 row)

Список tid незамороженных записей до горизонта заморозки («сломанных») можно получить запросом:

SELECT t_ctid
FROM generate_series(0, pg_relation_size('pg_catalog.pg_shdescription')/8192 - 1) s(i)
LEFT JOIN
LATERAL heap_page_items(get_raw_page('pg_catalog.pg_shdescription', s.i::int)) ON true
WHERE t_xmin::text::bigint < 512 AND
t_infomask & X'0300'::int <> X'0300'::int;

Пример вывода результата запроса:

    t_cid
-------------
(123456,65)
(123456,66)
(123456,67)
(123456,68)
(123456,69)
(123456,70)
(5 rows)

Скрипт для починки отношения можно подготовить с помощью запроса:

SELECT 'SELECT freeze_page(''pg_catalog.pg_shdescription'', '''||t_ctid||''');'
FROM generate_series(0, pg_relation_size('pg_catalog.pg_shdescription')/8192 - 1) s(i)
LEFT JOIN
LATERAL heap_page_items(get_raw_page('pg_catalog.pg_shdescription', s.i::int)) ON true
WHERE t_xmin::text::bigint < 512 AND
t_infomask & X'0300'::int <> X'0300'::int;

Пример вывода результата запроса:

                                ?column?
--------------------------------------------------------------------
SELECT freeze_page('pg_catalog.pg_shdescription', '(123456,65)');
SELECT freeze_page('pg_catalog.pg_shdescription', '((123456,66)');
SELECT freeze_page('pg_catalog.pg_shdescription', '((123456,67)');
SELECT freeze_page('pg_catalog.pg_shdescription', '((123456,68)');
SELECT freeze_page('pg_catalog.pg_shdescription', '((123456,69)');
SELECT freeze_page('pg_catalog.pg_shdescription', '((123456,70)');
(5 rows)

Выполните фриз полученным скриптом.

Пример вывода результата запроса:

 freeze_page
-------------
t
(1 rows)