49.5. Vérification de l'unicité de l'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.