Thanks to visit codestin.com
Credit goes to postgrespro.ru

F.2. amcheck

Модуль amcheck предоставляет функции, позволяющие проверять логическую целостность структуры индексов. Если нарушения структуры не обнаруживаются, эти функции отрабатывают без ошибок.

Эти функции проверяют различные инварианты в структуре представления определённых индексов. Правильность работы функций методов доступа, стоящих за сканированием индекса и другими важными операциями, зависит от всегда соблюдаемых инвариантов. Например, определённые функции проверяют, помимо остальных вещей, что все страницы B-дерева содержат элементы в «логическом» порядке (например, индекс-B-дерево, построенный по столбцу text, должен содержать кортежи, упорядоченные в лексическом порядке с учётом правила сортировки). Если этот конкретный инвариант каким-то образом нарушается, следует ожидать, что бинарный поиск на затронутой странице введёт в заблуждение процедуру сканирования индекса, что приведёт к неверным результатам запросов SQL.

Проверка выполняется теми же процедурами, что используются при сканировании индекса, и это может быть код пользовательского класса операторов. Например, проверка индекса-B-дерева задействует сравнения, выполняемые одной или несколькими опорными функциями B-дерева под номером 1. Подробнее опорные функции класса операторов описываются в Подразделе 37.14.3.

Функции amcheck могут выполнять только суперпользователи.

F.2.1. Функции

bt_index_check(index regclass) returns void

bt_index_check проверяет, соблюдаются ли в целевом объекте, индексе-B-дереве, различные инварианты. Пример использования:

test=# SELECT bt_index_check(c.oid), c.relname, c.relpages
FROM pg_index i
JOIN pg_opclass op ON i.indclass[0] = op.oid
JOIN pg_am am ON op.opcmethod = am.oid
JOIN pg_class c ON i.indexrelid = c.oid
JOIN pg_namespace n ON c.relnamespace = n.oid
WHERE am.amname = 'btree' AND n.nspname = 'pg_catalog'
-- Не проверять временные таблицы (они могут относиться к другим сеансам):
AND c.relpersistence != 't'
-- Функция может выдать ошибку без этих условий:
AND i.indisready AND i.indisvalid
ORDER BY c.relpages DESC LIMIT 10;
 bt_index_check |             relname             | relpages 
----------------+---------------------------------+----------
                | pg_depend_reference_index       |       43
                | pg_depend_depender_index        |       40
                | pg_proc_proname_args_nsp_index  |       31
                | pg_description_o_c_o_index      |       21
                | pg_attribute_relid_attnam_index |       14
                | pg_proc_oid_index               |       10
                | pg_attribute_relid_attnum_index |        9
                | pg_amproc_fam_proc_index        |        5
                | pg_amop_opr_fam_index           |        5
                | pg_amop_fam_strat_index         |        5
(10 rows)

Этот пример демонстрирует сеанс проверки 10 самых больших индексов системных каталогов в базе данных «test». Так как ошибки не было, все проверенные индексы представляются логически целостными. Естественно, этот запрос можно легко изменить, чтобы функция bt_index_check вызывалась для всех индексов в базе данных, которые поддерживают эту проверку.

Функция bt_index_check запрашивает блокировку AccessShareLock для целевого индекса и отношения, которому он принадлежит. Это тот же режим блокировки, что запрашивается для отношений обычными операторами SELECT. bt_index_check не проверяет инварианты, существующие в иерархии потомок/родитель, а также не проверяет, соответствует ли целевой индекс основному отношению. Когда в работающей производственной среде требуется регулярная лёгкая проверка на наличие нарушений, использование bt_index_check часто будет подходящим компромиссом между полнотой проверки и минимизацией влияния на производительность и доступность приложения.

bt_index_parent_check(index regclass) returns void

Функция bt_index_parent_check проверяет, соблюдаются ли в целевом объекте, индексе-B-дереве, различные инварианты. Проверки, выполняемые функцией bt_index_parent_check, включают в себя все проверки, которые выполняет bt_index_check. Функцию bt_index_parent_check можно считать более полноценным вариантом bt_index_check: в отличие от bt_index_check, bt_index_parent_check проверяет и инварианты, существующие в иерархии родитель/потомок. Однако и она не проверяет, соответствует ли целевой индекс основному отношению. Функция bt_index_parent_check следует общему соглашению и выдаёт ошибку в случае обнаружения логической несогласованности или другой проблемы.

Функция bt_index_parent_check запрашивает в целевом индексе блокировку ShareLock (также ShareLock запрашивается и в основном отношении). Эти блокировки предотвращают одновременное изменение данных командами INSERT, UPDATE и DELETE. Эти блокировки также препятствуют одновременной обработке нижележащего отношения командой VACUUM и другими вспомогательными командами. Заметьте, что эта функция удерживает блокировки только во время выполнения, а не на протяжении всей транзакции.

Дополнительные проверки, проводимые функцией bt_index_parent_check, более ориентированы на выявление различных патологических случаев. В том числе это может быть неправильно реализованный класс операторов B-дерева, используемый проверяемым индексом, или, гипотетически, неизвестные ошибки в нижележащем коде метода доступа индекса-B-дерева. Заметьте, что функцию bt_index_parent_check нельзя применять, когда включён режим горячего резерва (то есть на физических репликах в режиме «только чтение»), в отличие от bt_index_check.

F.2.2. Эффективное использование amcheck

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

  • Структурные несоответствия, возникающие при некорректной реализации класса операторов.

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

    Когда возникает подобная проблема, она может затрагивать не абсолютно все индексы, построенные с порочным правилом сортировки, просто потому что индексированные значения могут иметь тот же абсолютный порядок, независящий от различий поведения. За дополнительными сведениями об использовании в PostgreSQL правил сортировки и локалей операционной системы обратитесь к Разделу 23.1 и Разделу 23.2.

  • Повреждения, вызванные гипотетическими неизвестными ошибками в нижележащем коде методов доступа PostgreSQL или коде сортировки.

    Автоматическая проверка структурной целостности индексов играет важную роль в общем тестировании новых или предлагаемых возможностей PostgreSQL, с которыми может возникнуть логическая несогласованность. И поэтому одна из очевидных стратегий тестирования — регулярно вызывать функции amcheck при проведении стандартных регрессионных тестов. Подробнее о выполнении тестов можно узнать в Разделе 32.1.

  • Ошибки в файловой системе или подсистеме хранения, когда просто не включены контрольные суммы.

    Заметьте, что amcheck рассматривает страницу в том виде, как она представлена в некотором буфере разделяемой памяти к моменту проверки, если при обращению к нужному блоку он уже находится в разделяемом буфере. Вследствие этого, amcheck не обязательно видит данные, находящиеся в файловой системе в момент проверки. Заметьте, что когда контрольные суммы включены, amcheck может выдать ошибку из-за несоответствия контрольных сумм, если в буфер будет считываться испорченный блок.

  • Повреждения, вызванные дефектными чипами ОЗУ или вообще подсистемой памяти.

    PostgreSQL не защищает от ошибок памяти; предполагается, что в эксплуатируемом вами сервере установлена память с ECC (Error Correcting Codes, Коды исправления ошибок) или лучшая защита. Однако память ECC обычно защищает только от ошибок в одном бите и не следует считать её абсолютной защитой от сбоев, приводящих к повреждению памяти.

Вообще говоря, amcheck может доказать только наличие повреждений, но не доказать их отсутствие.

F.2.3. Исправление повреждений

Выдаваемые amcheck ошибки, относящиеся к повреждениям данных, никогда не должны быть ложными. На практике amcheck с большей вероятностью обнаружит программные ошибки, чем проблемы с оборудованием. amcheck выдаёт ошибки в случае условий, которые никогда не должны наблюдаться по определению, так что ошибки amcheck, как правило, требует тщательного анализа.

Общего метода устранения проблем, которые может выявить amcheck, не существует. Начать нужно с поиска корня проблемы, приводящей к нарушению инварианта. Полезную роль в диагностике повреждений, которые выявляет amcheck, может сыграть pageinspect. Одна лишь команда REINDEX может быть неэффективна, когда потребуется исправить повреждения.