MySQL - L'auto-incrémentation ne s'incrémente pas séquentiellement si la dernière ligne a été supprimée


8

J'ai une table qui contient un identifiant de clé primaire incrémenté automatiquement. Si je supprime la dernière ligne (id le plus élevé, pour exampe id = 6) et insère une nouvelle ligne, le nouvel id commence à 7. Quel paramètre dois-je changer pour que la clé primaire commence à 6?

CREATE TABLE animals (
 id MEDIUMINT NOT NULL AUTO_INCREMENT,
 name CHAR(30) NOT NULL,
 PRIMARY KEY (id)
) ENGINE=MyISAM;

INSERT INTO animals (name) VALUES
('dog'),('cat'),('penguin'),
('lax'),('whale'),('ostrich');

Résultat:
id nom
1 chien
2 chat
3 pingouin
4 lax
5 baleine
6 autruche

DELETE FROM animals WHERE id = 6;
INSERT INTO animals (name) VALUES
('x');

Résultat:
id nom
1 chien
2 chat
3 pingouin
4 lax
5 baleine
7 x

Merci du conseil.


Et s'il y a des lacunes? (qui peut apparaître pour plusieurs autres raisons, non seulement en supprimant des lignes)
ypercubeᵀᴹ

que voudriez-vous faire si la suppression se produit après une insertion? allez-vous réutiliser cet écart? est oui alors je ne pense pas que l'identité soit le bon type pour cette colonne. cela vous donne la possibilité de ne pas vous soucier des valeurs uniques dans cette colonne. si vous avez l'intention de conserver les valeurs dans l'ordre, vous pouvez simplement utiliser le type de données de type INT / BIGINT normal. trouver / réutiliser / réinitialiser des valeurs pour chaque lacune manquante, c'est comme renoncer à l'objectif de la propriété d'identité.
Anup Shah

@giordano Pourquoi voulez-vous être un monstre soigné de clé primaire AUTO_INCREMENT? pour y faire face il y a aussi un "gap" dans vos données de table si vous mettez à jour / supprimez à cause de la fragmentation ..
Raymond Nijland

J'ai fait une enquête sur les valeurs auto_increment continues pour SQL Server il y a quelque temps: sqlity.net/en/792/the-gap-in-the-identity-value-sequence - Bien que ce ne soit pas pour MySQL, les mécanismes sous-jacents sont les mêmes , vous obtiendrez donc des résultats similaires. En bref, vous ne pouvez pas empêcher les lacunes d'une séquence générée automatiquement.
Sebastian Meine

@ypercube: merci pour les réponses. En effet, l'écart que j'ai obtenu d'un autre exemple plus complexe, mais je voulais montrer un exemple minimal. Le véritable exemple était (1) de changer la date d'expiration d'une ligne (par exemple à partir d'une table de produits) en raison du changement d'un attribut et (2) d'ajouter le nouveau produit avec le même code de produit, le nouvel attribut, la nouvelle date effective et l'expiration ouverte Date. Ce qui s'est passé, c'est que la nouvelle clé primaire n'a pas été incrémentée automatiquement avec +1 mais +2. De toute évidence, à l'étape (1) ou (2), il y a un incrément automatique invisible. Je me demande quelle est l'autre raison des lacunes.
giordano

Réponses:


12

C'est de par leur conception - tous les SGBD agissent ainsi avec des colonnes à incrémentation automatique.

S'ils ne l'étaient pas, l'intégrité référentielle externe pourrait être endommagée. Pour un exemple simple de cela, imaginez que vous stockez des URL pour un service de raccourcissement en utilisant une colonne d'incrémentation automatique comme clé. Vous ne savez pas si l'URL raccourcie a déjà été distribuée à qui que ce soit, et la base de données ne le fait certainement pas, donc la réutilisation de l'ID 1234 pourrait entraîner la pauvre grand-mère de quelqu'un à visiter somenastypornsite.xxx au lieu de loverlyknitting.org lorsqu'elle clique sur http: / /shortthi.ng/1234 dans un ancien e-mail, au lieu de recevoir un message "Désolé mais ce lien n'existe plus dans nos enregistrements".

De plus, si vous réinitialisez l'incrément après avoir supprimé le dernier élément, allez-vous également effectuer tout le travail (ou vous attendre à ce que la base de données) renumérote tout après le 5ème élément de 5 millions lorsque le 5ème élément est supprimé? compléter avec les modifications apportées à d'autres tables lorsque leurs contraintes de clé étrangère pointent vers la colonne d'incrémentation Un tel travail supplémentaire pourrait devenir très coûteux en termes d'E / S.

Si vous faites réinitialiser le point incrément après la suppression du dernier élément, ne soyez très très prudent de vos niveaux d'isolation de transaction: Vous pouvez réinitialiser tout comme une autre transaction fait usage de la valeur, ce qui conduit à des erreurs (ou pire, échecs silencieux), à moins que vous vous assurez que votre action est entièrement isolée à 100%.

Je recommande généralement aux personnes travaillant avec des bases de données de lire "SQL Antipatterns" qui a un chapitre sur ce problème nommé "Psuedo-Key Neat Freaks" (qui couvre la question d'une manière plus conviviale que le titre du chapitre peut impliquer pour certains!). Essentiellement, si la valeur a une signification au-delà d'être une clé (ou tout au plus transportant des informations d'ordre d'insertion), alors elle ne devrait probablement pas être une colonne à incrémentation automatique, et si elle n'a pas de signification au-delà d'être une clé (ou tout au plus transportant un ordre d'insertion) informations), alors les lacunes ne devraient pas avoir d’importance.


Merci pour cette explication. Je vois que je dois approfondir le concept clé. Je me demande comment fonctionne le mécanisme d'incrémentation automatique, car j'ai également observé des lacunes dans la clé primaire lorsque je ne l'ai pas supprimée, mais j'ai modifié (mis à jour) une ligne et en a ajouté une nouvelle. En définitive, ce que je ne ferai pas, c'est de modifier manuellement la valeur d'incrémentation automatique.
giordano

En ce qui concerne "approfondir le concept clé", je recommande fortement le livre SQL Antipatterns de Bill Karwin - il couvre cela et un certain nombre d'autres sujets communs (et pas si communs), expliquant comment se tromper, pourquoi le mal commun Les méthodes peuvent causer des problèmes, comment les résoudre et quand la "mauvaise" méthode peut être OK à utiliser (ou le seul choix) de toute façon, de manière concise mais accessible.
David Spillett

Spillet: Merci pour cette indication. J'ai lu maintenant et c'était très utile. Néanmoins, je ne comprends pas pourquoi InnoDB et MyISAM comptent différemment: dba.stackexchange.com/questions/51883/…
giordano

0

Vous pouvez réinitialiser la valeur auto_increment en utilisant ce qui suit:

ALTER TABLE MyTable AUTO_INCREMENT = 1234;

Vous devez déterminer la valeur maximale présente dans le tableau et ajouter 1 à cette valeur à utiliser dans l'instruction ci-dessus.


Mauvaise idée, cela empêchera votre table de lire ou d'écrire dans "presque toutes" les versions de MySQL. MySQL 5.6 pourrait faire un LIVE ALTER mais parfois il doit également verrouiller la table.
Raymond Nijland

2
@RaymondNijland Je ne pense pas que le verrou durerait assez longtemps pour que quiconque le remarque.
ypercubeᵀᴹ

@Max, Raymond, ypercube: Merci pour la réponse. J'éviterai de faire ce genre de changement.
giordano
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.