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
может быть неэффективна, когда потребуется исправить повреждения.