Documentation PostgreSQL 8.2.23 > Internes > Définition de l'interface des méthodes d'accès aux index > Vérification de l'unicité de l'index | |
Considérations pour le verrouillage d'index | Fonctions d'estimation des coûts d'index |
PostgreSQL™ renforce les contraintes SQL d'unicité en utilisant les index uniques, qui sont des index qui refusent les entrées multiples avec des clés identiques. Une méthode d'accès qui supporte cette fonctionnalité initialise pg_am.amcanunique à true (à présent, seul B-tree le supporte).
Grâce à MVCC, il est toujours nécessaire d'autoriser les entrées dupliquées à exister physiquement dans un index : mes entrées pourraient faire référence à des versions successives d'une même ligne logique. Le comportement que nous voulons réellement renforcer est qu'aucune image MVCC n'inclut deux lignes avec les mêmes clés d'index. Ceci crée les différents cas suivants devant être vérifiés lors de l'insertion d'une nouvelle ligne dans un index unique :
Si une ligne valide en conflit a été supprimée par une transaction concurrente, tout va bien (en particulier, comme un UPDATE supprime toujours l'ancienne version de la ligne avant d'insérer la nouvelle version, ceci permettra un UPDATE sur une ligne sans changer la clé).
Si une ligne en conflit a été insérée par une transaction encore non validée, le soi-disant inséreur doit attendre de voir si la transaction est validée. Si la transaction est annulée, alors il n'y a pas de conflit. Si la transaction est validée sans que la ligne en conflit ait été supprimée, il y a une violation de la contrainte d'unicité (en pratique, nous attendons juste que l'autre transaction finisse et puis nous refaisons le contrôle de visibilité dans toto).
De façon similaire, si une ligne valide en conflit a été supprimée par une transaction encore non validée, l'inserteur doit attendre la validation ou l'annulation de cette transaction, puis recommence le test.
De plus, immédiatement avant de lever une violation d'unicité suivant les règles ci-dessus, la méthode d'accès doit de nouveau vérifier l'état de la ligne en cours d'insertion. Si elle est validée tout en étant morte, alors aucune erreur ne devrait survenir. (Ce cas ne peut pas survenir lors du scénario ordinaire d'insertion d'une ligne qui a été tout juste créée par la transaction en cours. Cela peut néanmoins arriver pendant CREATE UNIQUE INDEX CONCURRENTLY.)
Nous réclamons que la méthode d'accès à l'index applique ces tests eux-même, ce qui signifient qu'ils doivent attendre l'en-tête pour vérifier le statut de validation d'une ligne qui est affichée comme une clé dupliquée suivant le contenu de l'index. Ceci est sans aucun doute moche et non modulaire, mais il permet d'éviter un travail redondant : si nous faisons un test séparé, alors la recherche d'index pour une ligne en conflit pourrait être essentiellement répétée lors de la découverte d'emplacement pour insérer la nouvelle entrée d'index de ligne. De plus, il n'existe aucun moyen pour éviter des conditions rares sans que la vérification de contrainte ne soit une partie intégrale d'insertion du nouvel entrée d'index.
Le principale limitation de ce schéma est qu'il n'existe pas de façon aisée de supporter les vérifications d'unicité déferrées.