Précédent   Forum du club des développeurs et IT Pro > Bases de données > PostgreSQL
PostgreSQL Forum PostgreSQL. Avant de poster -> F.A.Q PostGreSQL Tutoriels PostGreSQL
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse
 
Outils de la discussion
Publicité
'
Vieux 09/01/2013, 18h34   #1
benazur
Invité de passage
 
Homme
Inscription : septembre 2012
Messages : 4
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : Bénin

Informations forums :
Inscription : septembre 2012
Messages : 4
Points : 1
Points : 1
Par défaut Rollback d'une séquence

Bonjour,
D'après la documentation, lorsque l'application annule une transaction, les numéros de séquences générées ne sont pas annulées. Ce qui crée des trous dans la liste des numéros. Existe-t-il une option dans pg qui oblige le rollback aussi des séquences et retourne le système à son état initial ?
Merci
benazur est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/01/2013, 18h47   #2
CetTer
Membre du Club
 
Homme Franck Theeten
Inscription : mars 2005
Messages : 59
Détails du profil
Informations personnelles :
Nom : Homme Franck Theeten
Localisation : Belgique

Informations forums :
Inscription : mars 2005
Messages : 59
Points : 59
Points : 59
Bonjour,

Oui en effet, cette limitation n'est pas liée au système, mais à la règle ACID.
Si deux transactions ont lieu en parallèle sur la même table, et qu'une des deux continue après le rollback de celle qui a échoué, rien ne garantit l'unicité des identifiants insérés par le processus déjà lancé, et le fait de réinitialiser la séquence risquerait de faire planter toutes les insertions ultérieures à leur tour.

Par contre vous pouvez manuellement réinitialiser la valeur initiale de la séquence sur la valeur maximale d'une colonne (+1), comme le montre la doc, mais il faut être sûr que ni la séquence ni la table ne sont accédées en écriture au moment de le faire:

http://www.postgresql.org/docs/8.1/s...esequence.html

Code :
1
2
3
4
 
BEGIN;
SELECT SETVAL('serial', max(id)) FROM distributors;
END;
En fait si vous voulez à tout prix des listes continues et que le système est très sollicité en écriture, il faut peut-être mieux séparer sur deux colonnes les valeurs des clés primaires et étrangères et laisser les séquences s'en occuper, et les valeurs continues qui permettent d'indexer "visuellement" les données, qui, peuvent être gérés dans des requêtes de type
Code :
1
2
 
INSERT INTO XXX (cle_primaire, cle_visuelle ...) SELECT NEXTVAL('sequence'), COALESCE(MAX(cle_visuelle)+1,1), ...FROM XXX:;
CetTer est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/01/2013, 19h15   #3
benazur
Invité de passage
 
Homme
Inscription : septembre 2012
Messages : 4
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : Bénin

Informations forums :
Inscription : septembre 2012
Messages : 4
Points : 1
Points : 1
Merci CetTer pour la réponse.
Peux tu expliciter un peu plus la deuxième solution, je n'ai pas bien compris.
En fait c'est pour une application de facturation, et des trous sont inacceptables.
benazur est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/01/2013, 20h09   #4
CetTer
Membre du Club
 
Homme Franck Theeten
Inscription : mars 2005
Messages : 59
Détails du profil
Informations personnelles :
Nom : Homme Franck Theeten
Localisation : Belgique

Informations forums :
Inscription : mars 2005
Messages : 59
Points : 59
Points : 59
Tu peux utliser l'instruction "setval" qui permet de forcer la modification de la valeur courante de la séquence.
http://dgriessinger.developpez.com/p...sql/sequences/

...et lui demander de réinitialiser la séquence sur la dernière valeur encodée dans la table où tu comptes insérer les données (le "MAX(id)" de l'exemple).
Code :
1
2
3
4
5
 
BEGIN;
SELECT SETVAL('serial', max(id)) FROM distributors;
END;
--(je me suis trompé, le "+1" n'a pas lieu d'être dans ma réponse précédente)
Si par exemple la dernière clé primaire "id" de la table "distributors" a la valeur "456", "nextval("serial")" retournera "457" après l'exécution de ce bout de code. Mais il faut être sûr que la séquence n'est pas modifiée à nouveau entre sa réinitialisation et la prochaine insertion, sinon on a à nouveau un trou...

Je n'ai jamais programmé quelque chose de ce type personnellement, mais il est sans doute possible de lancer cette instruction dans un trigger avec l'option DEFERABLE INITIALLY DEFERRABLE pour qu'elle soit exécutée juste une fois, juste avant la fin la transaction. Normalement cela devrait éviter les trous.

Un peu comme dans:
http://stackoverflow.com/questions/8...-in-postgresql
(mais l'exemple lance ici une boucle exécuté autant de fois qu'il y avait de lignes dans la transaction, alors que dans le cas que tu mentionnes la séquence ne devrait être modifiée qu'une fois à la fin de la transaction)
CetTer est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 10/01/2013, 04h17   #5
benazur
Invité de passage
 
Homme
Inscription : septembre 2012
Messages : 4
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : Bénin

Informations forums :
Inscription : septembre 2012
Messages : 4
Points : 1
Points : 1
Merci CetTer pour ton aide.
benazur est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 10/01/2013, 10h05   #6
estofilo
Modérateur
 
Inscription : octobre 2008
Messages : 1 707
Détails du profil
Informations personnelles :
Localisation : France, Paris (Île de France)

Informations forums :
Inscription : octobre 2008
Messages : 1 707
Points : 2 353
Points : 2 353
Si c'est pour réinitialiser la séquence à chaque fois qu'on en a besoin, la séquence n'est plus utile, d'autant plus qu'on perd la propriété de sérialisation du générateur de valeur.
C'est-à-dire que 2 sessions qui font select max(id) au même moment pourront se retrouver avec la même valeur.

Autant utiliser un vrai verrou:
Code :
1
2
3
4
5
BEGIN;
LOCK TABLE facture;
SELECT 1+max(numero_facture) FROM facture INTO variable;
.. créer la facture avec le nouveau numéro
COMMIT;
estofilo est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Cette discussion est résolue.
Outils de la discussion

Navigation rapide


Fuseau horaire GMT +2. Il est actuellement 11h01.


 
 
 
 
Partenaires

Hébergement Web