8
votes

Valeurs Auto_Increment dans Innodb?

J'utilise InnoDB pour un projet et comptez sur Auto_Increment. Ce n'est pas un problème pour la plupart des tables, mais pour les tables avec suppression, cela pourrait être un problème:

Auto_Increment Manipulation à Innodb

en particulier cette partie:

Colonne Auto_Increment Nommé AI_COL: Après le démarrage du serveur, pour le premier insert dans une table T, Innodb exécute l'équivalent de cette déclaration: Sélectionnez max (AI_COL) de T pour la mise à jour; InnoDB incrémente par l'une de la valeur extraite par la déclaration et l'attribue à la colonne et au compteur d'incrément automatique pour la table.

Ceci est un problème car pendant qu'il garantit que dans la table, la clé est unique, il y a des clés étrangères de cette table où ces clés ne sont plus uniques.

Le serveur MySQL fait / ne doit pas redémarrer souvent, mais cela se brise. Y a-t-il des façons simples autour de cela?


1 commentaires

Corrigé dans mysql 8.0: dev.mysql.com/worklog/task/?id=6204


5 Réponses :


1
votes

Utilisez une contrainte de clé étrangère avec "SET NULL" pour les mises à jour et les suppresses.


6 commentaires

C'est le problème. J'ai copié et collé la mauvaise chose, en fait.


Y a-t-il un problème? La valeur maximale est rapidement dérivée de votre Index . Il n'y a pas d'analyse de table impliquée.


J'ai ajouté un peu plus d'explications en haut, mais le problème est qu'il existe d'autres tables faisant référence à cette table, à l'aide de l'ID comme reçu. Pour ces tables, cette colonne n'est plus unique.


Je pense que vous êtes mal compris la documentation. Lorsque vous insérez une ligne, l'ID généré automatiquement est enregistré sur le disque. La seule chose qui n'est pas enregistrée sur le disque est la cache de la valeur suivante, mais cela n'affecte pas la fonctionnalité. Cela donne simplement une très performance mineure sur le démarrage.


Le problème de l'OP est celui-ci: Insérez une ligne avec ID = 42 dans un tablier. Insérez une autre ligne avec une clé étrangère (42) dans la tableb. Supprimer ID = 42 du tablier. Redémarrez maintenant le serveur et insérez une autre ligne de tablea. Il obtiendra ID = 42 et la clé étrangère de référencement dans la tableb signifierait désormais les données qui ne sont vraiment pas liées


@NOS: OK, ça a du sens. Je ne pouvais pas résoudre ce que le problème ressort de la description de la question, mais je le vois maintenant. Les solutions sont simples cependant: InnoDB prend en charge les contraintes de clé étrangère. Ainsi, lorsque vous supprimez la ligne, vous pouvez vous assurer qu'aucune autre ligne ne pointe toujours là. J'ai mis à jour ma réponse.



1
votes

Vous avez donc deux tables:

Tablea

a_id [pk]

et

TABLEB

b_id [pk]

a_id [fk, tablef.a_id]

et dans la tableb, la valeur d'A_ID n'est pas unique? Ou y a-t-il une valeur dans tableb.a_id qui n'est pas dans Tablea.a_id?

Si vous avez besoin de la valeur de tableb.a_id pour être unique, vous devez ajouter une contrainte unique à cette colonne.

ou est-ce que je manque toujours quelque chose?


1 commentaires

Il y a une contrainte unique, ce qui est de savoir comment cela me manque - il essaie d'insérer dans la tableB A_ID qui existe déjà, en raison du redémarrage du serveur et de la réinitialisation automatique de la réinitialisation.



3
votes

Si vous avez une contrainte de clé étrangère, comment pouvez-vous supprimer une rangée de la table A lorsque le tableau B références de cette ligne? Cela ressemble à une erreur pour moi.

Peu importe, vous pouvez éviter la réutilisation des valeurs d'incrémentation automatique en réinitialisant le décalage lorsque votre application recommence. Requête pour le maximum dans toutes les tables qui référent le tableau A, puis modifier le tableau ci-dessus sur ce maximum, par exemple. Si le MAX est 989, utilisez ceci: p>

alter table TableA auto_increment=999;


1 commentaires

Semble juste. Je l'utilise un peu comme un reçu, bien que je devrais peut-être prendre une autre approche.



1
votes

Créer une autre table avec une colonne qui se souvient de la dernière carte d'identité créée. De cette façon, vous n'avez pas à prendre en charge les valeurs maximales dans de nouvelles tables qui ont ceci comme clé étrangère.


0 commentaires

1
votes

j'ai vérifié. alter Tablea Tablea auto_incrènement = 1; ne marche pas. Et la raison pour laquelle j'ai trouvé dans deux documents

http: // docs. oracle.com/cd/e17952_01/Refman-5.1-fr/innodb-auto-Increment-handling.html InnoDB utilise l'algorithme suivant pour initialiser le compteur d'incrément automatique pour une table T contenant une colonne Auto_inCremmentation nommée AI_COL: après un démarrage du serveur, pour le premier insert dans une table T, Innodb exécute l'équivalent de cette déclaration: Sélectionnez max (AI_COL) de T pour la mise à jour; InnoDB incrémente la valeur extraite par la déclaration et l'attribue à la colonne et au compteur d'incrémentation automatique de la table. Par défaut, la valeur est incrémentée par une. Cette valeur par défaut peut être remplacée par le paramètre de configuration Auto_inCrementi_incrèce.

et http://docs.oracle.com/cd/e17952_01 /refman-5.1-fr/alter-Table.html

Vous ne pouvez pas réinitialiser le compteur à une valeur inférieure ou égale à celle qui a déjà été utilisée.

C'est la raison pour laquelle Alter Table ne fonctionnera pas. Je pense que seule l'option est d'essuyer les données et de la réécrire dans une nouvelle table avec un nouvel identifiant. Dans ma table de cas était logfile, alors je faisais juste:

Rename Table SystemEvents à SystemEvents_old; Créer une table SystemEvents comme SystemEvents_old;


0 commentaires