MySQL AUTO_INCREMENT ne pas ROLLBACK
Je suis en utilisant MySQL champ de type AUTO_INCREMENT et InnoDB pour soutenir les transactions. J'ai remarqué que quand je rollback de la transaction, le champ de type AUTO_INCREMENT n'est pas rollbacked? J'ai trouvé qu'il a été conçu de cette façon, mais existe-il des solutions de contournement pour cela?
- Juste une remarque: les valeurs auto_increment réinitialiser un max de+1 de la colonne après une réinitialisation du serveur.
- Ce n'est pas spécifique à mysql, Postgres se comporte de la même manière. Les explications du sens.
Vous devez vous connecter pour publier un commentaire.
Permettez-moi de vous faire remarquer quelque chose de très important:
Vous ne devez jamais dépendre du numérique dispose d'générée automatiquement les clés.
Qui est, autres que les comparant pour l'égalité (=) ou unequality (<>), vous ne devriez pas faire autre chose. Aucun des opérateurs relationnels (<, >), pas de tri par index, etc. Si vous avez besoin de trier par "date d'ajout", avoir une "date d'ajout" de la colonne.
De les traiter comme des pommes et des oranges: est-il judicieux de demander si une pomme est le même comme une orange? Oui. Est-il judicieux de demander si une pomme est plus gros qu'une orange? Pas de. (En fait, il n', mais vous avez mon point.)
Si vous vous en tenez à cette règle, les lacunes dans la continuité de l'générée automatiquement les index ne sera pas causer des problèmes.
Il ne peut pas travailler de cette façon. Considérer:
Comment fonctionne la base de données de récupérer l'557 valeur? Faut-il aller dans FOO et de décrémentation toutes les autres clés primaires de plus de 557? Comment est-il fixer la BARRE? Comment est-il effacer l'558 imprimé sur le rapport du programme des trois sortie?
Oracle numéros de séquence sont également indépendants des transactions pour la même raison.
Si vous pouvez résoudre ce problème en temps constant, je suis sûr que vous pouvez faire beaucoup d'argent dans le champ de base de données.
Maintenant, si vous avez une exigence particulière de votre auto incrément de terrain n'ont jamais lacunes (à des fins de vérification, par exemple). Ensuite, vous ne pouvez pas la restauration de vos transactions. Au lieu de cela vous devez disposer d'un indicateur d'état sur vos dossiers. Sur la première insertion, l'enregistrement de l'état est "Incomplète", puis vous commencez l'opération, de faire leur travail et de mettre à jour le statut de "concurrencer" (ou ce que vous avez besoin). Puis, quand vous vous engagez, l'enregistrement en direct. Si la transaction rollsback, l'incomplétude de l'enregistrement est toujours là pour l'audit. Cela vous fera beaucoup d'autres maux de tête, mais est un moyen de traiter avec les pistes d'audit.
J'ai eu un client qui avait besoin de l'ID de la restauration sur une table de factures, d'où la commande doit être consécutives
Ma solution dans MySQL était de supprimer l'AUTO-INCRÉMENTATION et tirez le dernier Id de la table, ajoutez un (+1), puis l'insérer manuellement.
Si la table est nommée "TableA" et l'Auto-incrémentation de la colonne est "Id"
(SELECT MAX(id) AS maxval FROM table_name;)+1
Pourquoi s'en faire si elle est annulée? AUTO_INCREMENT de la clé des champs ne sont pas censés avoir un sens de sorte que vous ne devriez vraiment pas attention à ce que la valeur est utilisée.
Si vous avez des informations que vous essayez de préserver, peut-être à un autre non-colonne de clé est nécessaire.
Je ne sais pas de toute façon de le faire. Selon le Documentation De MySQL, ce comportement est attendu et sera le cas avec tous innodb_autoinc_lock_mode modes de verrouillage. Le texte spécifique est:
Si vous définissez
auto_increment
à1
après une annulation ou d'une suppression, sur la prochaine insertion, MySQL va voir que1
est déjà utilisé et au lieu d'obtenir laMAX()
valeur et ajouter 1.Cela permettra d'assurer que si la ligne avec la dernière valeur est supprimée (ou l'insert est annulée), elle sera réutilisée.
Pour définir le type auto_increment à 1, faire quelque chose comme ceci:
Ce n'est pas aussi efficace que de simplement continuer avec le prochain numéro, car
MAX()
peuvent être coûteux, mais si vous supprimez/rollback rarement et sont obsédés par la réutilisation de la valeur la plus élevée, alors c'est une approche réaliste.Être conscient que cela n'empêche pas les lacunes d'enregistrements supprimés dans le milieu ou si un autre insert doit se produire avant que vous ne le réglage de type auto_increment à 1.
Si la table ne contient pas de valeurs ou des lignes nulles
ajouter une cible pour l'erreur mysql type de mise à jour à PARTIR sur une sélection de
SOLUTION:
Nous allons utiliser 'tbl_test" comme un exemple de tableau, et supposons que le champ 'Id' a l'attribut AUTO_INCREMENT
Supposons que le tableau a houndred ou milliers de lignes déjà inséré et vous ne voulez pas utiliser de type AUTO_INCREMENT plus; parce que quand vous la restauration d'une transaction le champ 'Id' est toujours à l'ajout de +1 à la valeur AUTO_INCREMENT.
Donc, pour éviter ce que vous pourriez faire ceci:
Que c'est! Vous avez terminé!
Si vous avez besoin d'avoir l'id dans l'ordre numérique, sans lacunes, alors vous ne pouvez pas utiliser une colonne d'auto-incrémentation. Vous aurez besoin de définir une norme colonne de type integer et utiliser une procédure stockée qui calcule le nombre suivant dans l'insertion de la séquence et insère l'enregistrement au sein d'une transaction. Si l'insertion échoue, alors la prochaine fois que la procédure est appelée, elle va recalculer le numéro suivant.
Cela dit, c'est une mauvaise idée de s'appuyer sur les numéros en cours dans un ordre particulier avec pas de lacunes. Si vous avez besoin de préserver l'ordre, vous devriez probablement timestamp de la ligne à insérer (et potentiellement sur la mise à jour).
Réponse concrète à ce dilemme (que j'ai eu) est la suivante:
1) Créer une table qui contient les différents compteurs de différents documents (factures, reçus, RMA, etc..); l'Insertion d'un enregistrement pour chacun de vos documents et d'ajouter l'initiale du compteur à 0.
2) Avant de créer un nouveau document, procédez de la manière suivante (pour les factures, par exemple):
3) pour Obtenir la dernière valeur que vous avez juste mis à jour, comme suit:
ou tout simplement utiliser votre PHP (ou autre) mysql_insert_id() fonction permettant d'obtenir la même chose
4) Insérez votre nouveau dossier avec l'ID primaire que vous venez de rentrer de la DB. Cela permettra de remplacer l'auto incrémentation de l'index, et assurez-vous que vous n'avez pas d'ID écarts entre les documents.
Cet ensemble doit être enveloppé à l'intérieur d'une transaction, bien sûr. La beauté de cette méthode est que, quand vous la restauration d'une transaction, votre instruction de mise à JOUR à partir de l'Étape 2 sera annulée, et le compteur ne changera plus. D'autres transactions simultanées se bloque jusqu'à ce que la première transaction soit validée ou annulée, donc ils n'auront pas accès à l'ancien comptoir OU un nouveau, jusqu'à ce que toutes les autres opérations sont a terminé la première.