2009-09-09 6 views
8

J'ai rencontré un comportement curieux aujourd'hui et je me demandais si c'était prévu ou standard. Nous utilisons Hibernate contre MySQL5. Au cours du codage j'ai oublié de fermer une transaction, je suppose que d'autres peuvent se rapporter.Transactions de base de données non validées et colonnes à incrémentation automatique

Lorsque j'ai finalement fermé la transaction, exécuté le code et vérifié la table, j'ai remarqué ce qui suit. Toutes les fois où j'ai exécuté mon code par erreur sans fermer la transaction, qui n'a donc pas entraîné l'insertion de lignes réelles, j'ai incrémenté la valeur de la clé primaire de substitution automatique, de sorte que j'ai un écart (ie 751 à 762).

Est-ce un comportement standard ou attendu? Cela peut-il varier en fonction de la base de données? Et/ou l'abstraction des transactions de Hibernate a-t-elle un effet possible?

+0

Je connaissais la réponse, mais c'est toujours une question intéressante! – RichardOD

+1

Idéalement, votre application/conception ne devrait pas être affectée par des lacunes dans la séquence - vous ne devriez jamais vous mettre dans une situation où cela importe vraiment –

Répondre

8

Oui c'est prévu.

Si vous y réfléchissez: que peut faire la base de données? Si vous incrémentez la colonne, puis l'utilisez comme clé étrangère dans d'autres insertions au sein de la même transaction et pendant que vous faites cela, quelqu'un d'autre s'engage à ne pas utiliser votre valeur. Vous aurez un écart.

Les séquences dans des bases de données comme Oracle fonctionnent de la même manière. Une fois qu'une valeur particulière est demandée, qu'elle soit ou non validée n'a pas d'importance. Ça ne sera jamais réutilisé. Et les séquences ne sont pas absolument ordonnées aussi.

6

C'est un comportement plutôt attendu. Sans cela, la base de données devrait attendre que chaque transaction qui a inséré un enregistrement se termine avant d'attribuer un nouvel identifiant à l'insertion suivante.

5

Oui, ce comportement est attendu. This documentation l'explique très bien. Depuis le 5.1.22, il existe actuellement trois modes de verrouillage différents qui contrôlent la manière dont les transactions simultanées obtiennent des valeurs d'incrémentation automatique. Mais tous les trois provoqueront des écarts pour les transactions annulées (les valeurs d'auto-incrémentation utilisées par la transaction annulée seront rejetées).

0

Les séquences de bases de données ne garantissent pas la séquence d'identifiants sans espaces. Ils sont conçus pour être indépendants de la transaction, seulement de cette manière peuvent être non bloquants.

Vous ne voulez pas de lacunes, vous devez écrire votre propre procédure stockée pour augmenter la colonne transactionnelle, mais un tel code va bloquer d'autres transactions, vous devez donc être prudent.

Vous ne sélectionnez SELECT CURRVAL FROM SEQUENCE_TABLE OERE TYPE =: YOUR_SEQ_NAME FOR UPDATE; MISE À JOUR SEQUENCE_TABLE SET CURRVAL =: INCREMENTED_CURRVAL WHERE TYPE =: VOTRE_SEQ.

Questions connexes