F.2. amcheck#

F.2. amcheck

F.2. amcheck

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

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

Проверка выполняется с использованием тех же процедур, что и при сканировании индекса, которые могут быть определены пользователем в виде кода класса операторов. Например, проверка индекса B-Tree основана на сравнениях, выполняемых с помощью одной или нескольких функций поддержки B-Tree. См. Раздел 36.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. Опытные пользователи также могут найти эту информацию полезной, поскольку она предоставляет дополнительный контекст в случае обнаружения несоответствия при проверке. Запуск:

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

Номер блока, содержащего поврежденную страницу.

offnum

The OffsetNumber of the corrupt tuple.

attnum

Атрибут номера поврежденного столбца в кортеже, если повреждение относится к конкретному столбцу, а не к кортежу в целом.

msg

Сообщение, описывающее обнаруженную проблему.

F.2.2. Опциональная проверка heapallindexed

Когда аргумент heapallindexed функций проверки B-дерева установлен в true, выполняется дополнительная фаза проверки для таблицы, связанной с целевым индексом. Она состоит из операции dummy CREATE INDEX, которая проверяет наличие всех гипотетических новых кортежей индекса во временной структуре, хранящейся в памяти (она создается при необходимости во время основной первой фазы проверки). Суммирующая структура отпечатывает каждый кортеж, найденный в целевом индексе. Основной принцип проверки heapallindexed заключается в том, что новый индекс, эквивалентный существующему целевому индексу, должен содержать только записи, которые можно найти в существующей структуре.

Дополнительная фаза heapallindexed добавляет значительные издержки: проверка обычно занимает несколько раз больше времени. Однако, при выполнении проверки heapallindexed не происходит изменения блокировок на уровне отношений.

Структура сводки ограничена размером maintenance_work_mem. Чтобы гарантировать, что вероятность необнаружения несоответствия для каждой кортежа кучи, которая должна быть представлена в индексе, не превышает 2%, требуется примерно 2 байта памяти на каждый кортеж. По мере уменьшения доступной памяти на каждый кортеж, вероятность пропуска несоответствия медленно увеличивается. Такой подход значительно ограничивает издержки на проверку, при этом незначительно снижая вероятность обнаружения проблемы, особенно для установок, где проверка рассматривается как регулярная задача по обслуживанию. Каждая отсутствующая или неправильно сформированная кортежа имеет новую возможность быть обнаруженной при каждой новой попытке проверки.

F.2.3. Использование amcheck эффективно

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

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

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

    Если возникает такая проблема, это может и не повлиять на каждый отдельный индекс, упорядоченный с использованием затронутого правила сортировки, просто потому что значения, на которых основан индекс, могут иметь одинаковый абсолютный порядок, независимо от поведенческой несогласованности. См. Раздел 23.1 и Раздел 23.2 для получения дополнительной информации о том, как Tantor SE использует локали и правила сортировки операционной системы.

  • Структурные несоответствия между индексами и отношениями кучи, которые индексируются (при выполнении проверки heapallindexed).

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

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

    Automatic verification of the structural integrity of indexes plays a role in the general testing of new or proposed Tantor SE features that could plausibly allow a logical inconsistency to be introduced. Verification of table structure and associated visibility and transaction status information plays a similar role. One obvious testing strategy is to call amcheck functions continuously when running the standard regression tests

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

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

  • Повреждение, вызванное неисправной оперативной памятью или более широкой подсистемой памяти.

    Tantor SE не защищает от исправимых ошибок памяти, и предполагается, что вы будете работать с ОЗУ, использующей стандартные коды исправления ошибок (ECC) или более надежную защиту. Однако ECC-память обычно устойчива только к однобитовым ошибкам и не следует полагать, что она обеспечивает абсолютную защиту от сбоев, приводящих к повреждению памяти.

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

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

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

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

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

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

F.2.4. Восстановление повреждений

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

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