Le module amcheck
fournit des fonctions vous permettant
de vérifier la cohérence logique de la structure des index. Si la structure
semble valide, aucune erreur n'est levée.
Les fonctions vérifient diverses propriétés invariables
dans la structure de la représentation de certains index. La justesse des
fonctions permettant l'accès aux données durant les parcours d'index et
d'autres opération importantes reposent sur le fait que ces propriétés
invariables soient toujours vraies. Par exemple, certaines fonctions
vérifient, entre autres choses, que toutes les pages d'index B-Tree ont leurs
éléments dans un ordre « logique » (par exemple, pour des index
B-Tree sur un type text
, les lignes de l'index devraient être
triées dans l'ordre alphabétique défini par la collation). Si, quelque soit
la raison, cette propriété invariable spécifique n'est plus vérifiée, il
faut s'attendre à ce que des recherches binaires sur la page affectée
renseignent de manière erronée les parcours d'index, avec pour conséquence
des résultats erronnés aux requêtes SQL.
La vérification est réalisée en utilisant les même précédures que celles utilisées par les parcours d'index eux-même, qui peuvent très bien être du code utilisateur pour une classe d'opérateur. Par exemple, la vérification d'index B-Tree s'appuie sur les comparaisons faites avec une ou plusieurs routines pour la fonction de support 1. See Section 37.14.3 pour plus de détail sur les fonctions de support des classes d'opérateur.
Les fonctions du module amcheck
ne peuvent être
exécutées que par des super utilisateurs.
bt_index_check(index regclass) returns void
bt_index_check
que sa cible, un index B-Tree,
respecte une vériété de propriétés invariables. Exemple d'utilisation :
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' -- Ignore les tables temporaires, qui peuvent appartenir à d'autres sessions AND c.relpersistence != 't' -- La fonction peut renvoyer une erreur si cela est omis : 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)
Cet exemple montre une session qui effectue une vérification des dix plus
gros index sur le catalogue dans la base de données « test ».
Puisqu'aucune erreur n'est retournée, tous les index testés semblent être
cohérent au niveau logique. Bien évidemment, cette requête pourrait être
facilement modifiée pour appeler bt_index_check
sur
chacun des index présents dans la base de données pour lesquels la
vérification est supportée.
bt_index_check
acquiert un
AccessShareLock
sur l'index cible ainsi que sur la
relation à laquelle il appartient. Ce niveau de verrouillage est le même
que celui acquis sur les relations lors d'une simple requête
SELECT
statements.
bt_index_check
ne vérifie pas les propriétés
invariantes qui englobent les relations enfant/parent, et ne vérifie pas
non plus que l'index est cohérent par rapport au contenu de la relation
associée. Quand un test léger, de routine, pour détecter des problèmes
de corruption est nécessaire sur un environnement de production, utiliser
bt_index_check
offre généfalement le meilleur
compromis entre la minutie de la vérification et l'impact limité sur les
performances de l'application ainsi que sa disponibilité.
bt_index_parent_check(index regclass) returns void
bt_index_parent_check
teste que sa cible, un index
B-Tree, respecte un certain nombre de propriétés invariantes. Les
vérifications effectuées par bt_index_parent_check
sont un sur-ensemble des vérifications effectuées par
bt_index_check
.
On peut voir bt_index_parent_check
comme une version
plus minitieuse de bt_index_check
:
contrairement à bt_index_check
,
bt_index_parent_check
vérifie également les
propriétés invariantes qui englobent les relations parent/enfant.
Cependant, cette fonction ne vérifie pas que l'index cible est cohérent
avec la relation associée. bt_index_parent_check
respecte la convention habituelle qui consiste à retourner une erreur si
une incohérence ou tout autre problème est détecté.
Un verrou de type ShareLock
est requis sur l'index
ciblé par bt_index_parent_check
(un verrou de type
ShareLock
est également acquis sur la relation
associée). Ces verrous empêchent des modifications concurrentes par des
commandes INSERT
, UPDATE
, et
DELETE
Les verrous empêchent également la relation
associée d'être traitée de manière concurrente par
VACUUM
, ainsi que toute autre commande qui n'est pas
un ordre DML. Il est à noter que cette fonction conserve les verrous
uniquement durant son exécution et non pas durant l'intégralité de la
transaction.
La vérification supplémentaire de
bt_index_parent_check
est plus apte à détecter
différents cas pathologiques. Ces cas peuvent impliquer une classe
d'opérateur B-Tree implémentée de manière incorrecte utilisée pout
l'index vérifié, ou, hypothétiquement, des bugs non encore découverts
dans le code de la méthode d'accès assocée à cet index B-Tree. Il est à
noter que bt_index_parent_check
ne peut pas être
utilisé lorsque le mode Hot Standby est activé (c'est-à-dire, sur un
serveur secondaire disponible en lecture seule), contrairement à
bt_index_check
.
amcheck
efficacement
amcheck
peut être efficace pour détecter différents
types de modes d'échec que les sommes de contrôle de
page n'arriveront jamais à détecter. Cela inclut :
Les incohérences structurelles causée par des implémentations incorrectes de classe d"opérateur.
Cela inclue également des problèmes causés par le changement des règles de
comparaison des collations du système d'exploitation. Les comparaisons
des données d'un type ayant une collation comme text
doivent
être immuables (tout comme toutes les autres comparaisons utilisées pour
les parcours d'index B-Tree doivent être immuables), ce qui implique que
les règles de collation du système d'exploitation ne dois jamais changer.
Bien que cela soit rare, des mises à jour des règles des collations du
système d'exploitation peuvent causer ces problèmes. Plus généralement,
une incohérence dans l'ordre de collation entre un serveur primaire et son
réplicat est impliqué, peut-être parce que la version
major du système d'exploitation utilisée était
incohérente. De telles incohérences ne surviendront généralement que sur
des serveur secondaires, et ne pourront par conséquent être détectées que
sur des serveurs secondaires.
Si un tel problème survient, il se peut que cela n'affecte par individuellement chaque index qui utilise le tri d'une collation affectée, tout simplement car les valeurs indexée pourraient avoir le même ordre de tri absolu indépendamment des incohérences comportementales. Voir Section 23.1 et Section 23.2 pour plus de détails sur comment PostgreSQL utilise les locales et collations du système d'exploitation.
Une corruption causée par un hypothétique bug non encore découvert dans l'implémentation associée à la méthode d'accès ou au code effectuant le tri.
La vérification automatique de l'intégrité structurelle des index joue un
rôle sur les principaux tests des fonctionnalités nouvelles ou proposées
dans PostgreSQL qui pourraient possiblement
autoriser l'introduction d'incohérence logiques. Une stratégie de test
évidente est d'appeler les fonctions d'amcheck
de
manière continue en même temps que les tests de régression standard sont
lancés. Voir Section 32.1 pour plus de détail sur commencer lancer les
tests.
Les défauts du système de fichiers ou du sous système de stockage quand les vérifications des sommes de contrôles ne sont pas activées.
Il est à noter que amcheck
examine les pages telles
que représentées dans des tampons en mémoire partagée au moment de la
vérification s'il y a seulement un accès en mémoire partagée lors de
l'accès au bloc. Par conséquent, amcheck
n'examine
pas forcément les données lues depuis le système de fichiers au moment de
la vérification. De plus, quand les sommes de contrôles sont activées,
amcheck
peut lever une erreur de somme de contrôle
incorrecte quand un block corrompu est lu vers un tampon.
Les corruptions causée par une mémoire RAM défaillante, et plus largement le sous système mémoire.
PostgreSQL ne protège pas contre les erreurs mémoire corrigibles et il est supposé que vous utilisez de la mémoire RAM utilisant le standard de l'instrie Error Correcting Codes (ECC) ou une meilleure protection. Cependant, la mémoire ECC est typiquement immunisée uniquement contre les erreurs d'un seul bit, et il ne faut pas partir du principe que ce type de mémoire fournit une protection absolue contre les défaillances résultant en une corruption mémoire.
De manière générale, amcheck
ne peut que prouver la
présence d'une corruption; il ne peut pas en prouver l'absence.
Aucune erreur concernant une corruption remontée par
amcheck
ne devrait être un faux positif. Dans la
pratique, amcheck
est plus à même de trouver des bugs
logiciels que des problèmes matériels.
amcheck
remonte des erreurs dans le cas où des
conditions, par définition, ne devraient jamais arriver, et par conséquent
une analyse minutieuse des erreurs remontées par amcheck
est souvent nécessaire.
Il n'y a pas de méthode générale pour réparer les problèmes que
amcheck
détecte. Une explication de la cause principale
menant à ce que la propriété invariable soit violée devrait être étudiée.
pageinspect pourrait jouer un rôle utile dans le
diagnostique de la corruption qu'amcheck
détecte. Un
REINDEX
pourrait ne pas être efficace pour réparer la
corruption.