F.2. amcheck — инструменты для проверки согласованности таблиц и индексов#
F.2. amcheck — инструменты для проверки согласованности таблиц и индексов #
Модуль amcheck предоставляет функции, которые позволяют
проверить логическую согласованность структуры отношений.
Функции проверки B-дерева проверяют различные инварианты в структуре представления конкретных отношений. Правильность функций метода доступа, лежащих в основе индексных сканирований и других важных операций, зависит от того, что эти инварианты всегда выполняются. Например, некоторые функции проверяют, среди прочего, что все страницы B-дерева имеют элементы в “логическом” порядке (например, для индексов B-дерева на типе text, кортежи индекса должны быть в лексикографическом порядке). Если этот конкретный инвариант по какой-то причине не выполняется, можно ожидать, что бинарные поиски на затронутой странице неправильно направят индексные сканирования, что приведет к неправильным ответам на SQL-запросы. Если структура кажется действительной, ошибки не возникает.
Проверка выполняется с использованием тех же процедур, что и при сканировании индекса, которые могут быть определены пользователем в виде кода класса операторов. Например, проверка индекса B-Tree основана на сравнениях, выполняемых с помощью одной или нескольких функций поддержки B-Tree. См. Раздел 35.15.3 для получения подробной информации о функциях поддержки класса операторов.
В отличие от функций проверки B-дерева, которые сообщают о повреждении, вызывая ошибки, функция проверки кучи verify_heapam проверяет таблицу и пытается вернуть набор строк, одну строку на каждое обнаруженное повреждение. Несмотря на это, если средства, от которых зависит verify_heapam, также повреждены, функция может быть неспособна продолжить работу и вместо этого вызовет ошибку.
Разрешение на выполнение функций amcheck может быть предоставлено не суперпользователям, но перед предоставлением таких разрешений следует тщательно продумать вопросы безопасности данных и конфиденциальности. Хотя отчеты о повреждениях, создаваемые этими функциями, не ставят своей целью содержание поврежденных данных, а скорее структуру этих данных и характер обнаруженных повреждений, злоумышленник, получивший разрешение на выполнение этих функций, особенно если он также может вызвать повреждение, может сделать выводы о самих данных на основе таких сообщений.
F.2.1. Функции #
-
bt_index_check(index regclass, heapallindexed boolean) returns void bt_index_checkпроверяет, что его цель, индекс B-Tree, соблюдает различные инварианты. Пример использования:test=# SELECT bt_index_check(index => c.oid, heapallindexed => i.indisunique), 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' -- Don't check temp tables, which may be from another session: AND c.relpersistence != 't' -- Function may throw an error when this is omitted: AND c.relkind = 'i' 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не проверяет инварианты, которые охватывают отношения родитель/потомок, но будет проверять наличие всех кортежей кучи в качестве индексных кортежей в индексе, когдаheapallindexedравноtrue. Когда требуется процедуральное, легкое тестирование на повреждения в рабочей среде, использованиеbt_index_checkчасто обеспечивает наилучший баланс между тщательностью проверки и ограничением влияния на производительность и доступность приложения.-
bt_index_parent_check(index regclass, heapallindexed boolean, rootdescend boolean) returns void bt_index_parent_checkпроверяет, что его цель, индекс B-Tree, соблюдает различные инварианты. При необходимости, когда аргументheapallindexedравенtrue, функция проверяет наличие всех кортежей кучи, которые должны быть найдены внутри индекса. Когда опциональный аргументrootdescendравенtrue, проверка повторно находит кортежи на уровне листьев, выполняя новый поиск с корневой страницы для каждого кортежа. Проверки, которые могут быть выполнены с помощью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следует общему соглашению о вызове ошибки, если он обнаруживает логическое несоответствие или другую проблему.Для целевого индекса требуется
ShareLock, который проверяется функциейbt_index_parent_check(также получаетсяShareLockна связанное отношение кучи). Эти блокировки предотвращают одновременное изменение данных командамиINSERT,UPDATEиDELETE. Блокировки также предотвращают одновременную обработку базового отношения командойVACUUM, а также всеми другими утилитами. Обратите внимание, что функция удерживает блокировки только во время выполнения, а не на всю транзакцию.Дополнительная проверка
bt_index_parent_checkскорее всего обнаружит различные патологические случаи. Эти случаи могут включать неправильно реализованный класс операторов B-Tree, используемый проверяемым индексом, или, гипотетически, необнаруженные ошибки в коде метода доступа к базовому индексу B-Tree. Обратите внимание, чтоbt_index_parent_checkне может использоваться, когда включен режим горячего резервирования (т.е. на только для чтения физических репликах), в отличие отbt_index_check.
Подсказка
bt_index_check и
bt_index_parent_check оба выводят сообщения журнала
о процессе проверки на уровнях серьезности DEBUG1 и
DEBUG2. Эти сообщения предоставляют подробную информацию
о процессе проверки, которая может быть интересна разработчикам
Tantor SE-1C. Опытные пользователи также могут
найти эту информацию полезной, поскольку она предоставляет дополнительный
контекст в случае обнаружения несоответствия при проверке. Запуск:
SET client_min_messages = DEBUG1;
в интерактивной сессии psql перед выполнением запроса на проверку будут отображаться сообщения о ходе проверки с уровнем детализации, который можно управлять.
-
verify_heapam(relation regclass, on_error_stop boolean, check_toast boolean, skip text, startblock bigint, endblock bigint, blkno OUT bigint, offnum OUT integer, attnum OUT integer, msg OUT text) returns setof record Проверяет таблицу, последовательность или материализованное представление на структурную поврежденность, где страницы в отношении содержат данные, которые имеют неверный формат, и на логическую поврежденность, где страницы структурно допустимы, но несогласованы с остальной частью кластера базы данных.
Следующие необязательные аргументы распознаются:
on_error_stopЕсли значение true, проверка повреждений останавливается в конце первого блока, в котором обнаружены повреждения.
По умолчанию установлено значение false.
check_toastЕсли значение true, тоастовые значения проверяются с таблицей TOAST целевого отношения.
Этот параметр известен своей медлительностью. Кроме того, если таблица toast или ее индекс повреждены, проверка ее по значениям toast может потенциально вызвать сбой сервера, хотя во многих случаях это просто приведет к ошибке.
По умолчанию установлено значение false.
skipЕсли не указано
none, проверка на повреждения пропускает блоки, которые помечены как полностью видимые или полностью замороженные, как указано. Допустимыми вариантами являютсяall-visible,all-frozenиnone.По умолчанию
none.startblockЕсли указан, проверка целостности начинается с указанного блока, пропуская все предыдущие блоки. Ошибка указать
startblockза пределами диапазона блоков в целевой таблице.По умолчанию проверка начинается с первого блока.
endblockЕсли указан, проверка целостности заканчивается на указанном блоке, пропуская все оставшиеся блоки. Ошибка указать
endblockза пределами диапазона блоков в целевой таблице.По умолчанию все блоки отмечены.
Для каждой обнаруженной коррупции
verify_heapamвозвращает строку со следующими столбцами:blknoНомер блока, содержащего поврежденную страницу.
offnumOffsetNumber поврежденного кортежа.
attnumАтрибут номера поврежденного столбца в кортеже, если повреждение относится к конкретному столбцу, а не к кортежу в целом.
msgСообщение, описывающее обнаруженную проблему.
F.2.2. Опциональная проверка heapallindexed #
Когда аргумент heapallindexed функций проверки B-дерева установлен в true, выполняется дополнительная фаза проверки по отношению к таблице, связанной с целевым индексом. Эта фаза состоит из “фиктивной” операции CREATE INDEX CONCURRENTLY, которая проверяет наличие всех гипотетических новых индексных кортежей с помощью временной сводной структуры, находящейся в памяти (эта структура создаётся при необходимости во время основной первой фазы проверки). Сводная структура “помечает” каждый кортеж, найденный в целевом индексе. Основной принцип проверки heapallindexed заключается в том, что новый индекс, равнозначный существующему целевому, должен содержать только те записи, которые уже присутствуют в существующей структуре.
Дополнительная фаза heapallindexed добавляет значительные издержки: проверка обычно занимает несколько раз больше времени. Однако, при выполнении проверки heapallindexed не происходит изменения блокировок на уровне отношений.
Структура сводки ограничена размером maintenance_work_mem. Чтобы гарантировать, что вероятность необнаружения несоответствия для каждой кортежа кучи, которая должна быть представлена в индексе, не превышает 2%, требуется примерно 2 байта памяти на каждый кортеж. По мере уменьшения доступной памяти на каждый кортеж, вероятность пропуска несоответствия медленно увеличивается. Такой подход значительно ограничивает издержки на проверку, при этом незначительно снижая вероятность обнаружения проблемы, особенно для установок, где проверка рассматривается как регулярная задача по обслуживанию. Каждая отсутствующая или неправильно сформированная кортежа имеет новую возможность быть обнаруженной при каждой новой попытке проверки.
F.2.3. Использование amcheck эффективно #
amcheck может быть эффективным в обнаружении различных типов
сбоев, которые контрольные суммы данных не смогут обнаружить. Это включает в себя:
Структурные несоответствия, вызванные неправильной реализацией класса операторов.
Это включает проблемы, вызванные изменением правил сортировки операционной системы. Сравнения данных типа
textдолжны быть постоянными (как и все сравнения, используемые для сканирования индекса B-Tree), что подразумевает, что правила сортировки операционной системы никогда не должны изменяться. Хотя это редко, обновления правил сортировки операционной системы могут вызывать эти проблемы. Более часто возникает несоответствие в порядке сортировки между основным сервером и резервным сервером, возможно, из-за несогласованности используемой основной версии операционной системы. Такие несоответствия, как правило, возникают только на резервных серверах и, следовательно, могут быть обнаружены только на резервных серверах.Если возникает такая проблема, это может и не повлиять на каждый отдельный индекс, упорядоченный с использованием затронутого правила сортировки, просто потому что значения, на которых основан индекс, могут иметь одинаковый абсолютный порядок, независимо от поведенческой несогласованности. См. Раздел 22.1 и Раздел 22.2 для получения дополнительной информации о том, как Tantor SE-1C использует локали и правила сортировки операционной системы.
Структурные несоответствия между индексами и отношениями кучи, которые индексируются (при выполнении проверки
heapallindexed).Во время нормальной работы не выполняется перекрестная проверка индексов по отношению к их куче. Симптомы повреждения кучи могут быть незаметными.
Повреждение, вызванное гипотетическими необнаруженными ошибками в основном коде метода доступа к Tantor SE-1C, коде сортировки или коде управления транзакциями.
Автоматическая проверка структурной целостности индексов играет важную роль в общем тестировании новых или предлагаемых Tantor SE-1C функций, которые могут потенциально привести к логической несогласованности. Проверка структуры таблицы и связанной с ней информации о видимости и состоянии транзакции выполняет аналогичную роль. Одна из очевидных стратегий тестирования - непрерывный вызов функций
amcheckпри запуске стандартных регрессионных тестов.Сбои файловой системы или подсистемы хранения, где контрольные суммы случайно не включены.
Обратите внимание, что
amcheckанализирует страницу, представленную в некотором общем буфере памяти во время проверки, если при доступе к блоку произошло только попадание в общий буфер. Следовательно,amcheckне обязательно анализирует данные, считанные из файловой системы во время проверки. Обратите внимание, что при включенных контрольных суммахamcheckможет вызвать ошибку из-за несоответствия контрольной суммы, когда поврежденный блок считывается в буфер.Повреждение, вызванное неисправной оперативной памятью или более широкой подсистемой памяти.
Tantor SE-1C не защищает от исправимых ошибок памяти, и предполагается, что вы будете работать с ОЗУ, использующей стандартные коды исправления ошибок (ECC) или более надежную защиту. Однако ECC-память обычно устойчива только к однобитовым ошибкам и не следует полагать, что она обеспечивает абсолютную защиту от сбоев, приводящих к повреждению памяти.
Когда выполняется проверка
heapallindexed, обычно существует значительно больший шанс обнаружения однобитных ошибок, поскольку выполняется строгое бинарное сравнение и проверяются индексированные атрибуты внутри кучи.
Структурная поврежденность может произойти из-за неисправного аппаратного обеспечения хранения или перезаписи или изменения файлов связей несвязанным программным обеспечением. Такого рода повреждение также может быть обнаружено с помощью контрольных сумм страниц данных.
Страницы отношений, которые правильно отформатированы, внутренне согласованы и корректны относительно своих собственных контрольных сумм, могут все равно содержать логическую поврежденность. Такие повреждения невозможно обнаружить с помощью контрольных сумм. Примеры включают тостовые значения в основной таблице, которым не соответствует запись в тостовой таблице, и кортежи в основной таблице с идентификатором транзакции, который старше самого старого допустимого идентификатора транзакции в базе данных или кластере.
В производственных системах было замечено множество причин логической поврежденности, включая ошибки в серверном программном обеспечении Tantor SE-1C, неисправные и неудачные инструменты резервного копирования и восстановления, а также ошибки пользователей.
Поврежденные отношения являются наиболее критичными проблемами в реальных производственных средах, именно там, где рискованные действия не желательны. По этой причине была разработана функция verify_heapam для диагностики повреждений без излишних рисков. Она не может защитить от всех причин сбоев бэкенда, так как даже выполнение вызывающего запроса может быть небезопасным в случае серьезного повреждения системы. Доступ к каталожным таблицам выполняется и может вызывать проблемы, если сами каталоги повреждены.
Обычно, amcheck может только доказать наличие повреждений; он не может доказать их отсутствие.
F.2.4. Восстановление повреждений #
Не должно возникать ошибок, связанных с повреждением, вызванных amcheck, которые могут быть ложными срабатываниями. amcheck вызывает ошибки в случае условий, которые, по определению, не должны происходить, поэтому часто требуется тщательный анализ ошибок amcheck.
Нет общего метода для устранения проблем, которые обнаруживает amcheck. Следует искать объяснение корневой причины нарушения инварианта. pageinspect может сыграть полезную роль в диагностировании повреждений, которые обнаруживает amcheck. REINDEX может быть неэффективным при восстановлении повреждений.