web-dev-qa-db-fra.com

L'incrément d'identité saute dans la base de données SQL Server

Dans l'une de mes tables, Fee de la colonne "ReceiptNo" dans l'incrément d'identité de la base de données SQL Server 2012 a soudainement commencé à passer à 100 au lieu de 1, en fonction des deux choses suivantes.

  1. s'il est 1205446, il saute à 1206306, s'il est 1206321, il saute à 1207306 et s'il est 1207314, il passe à 1208306. Ce que je veux vous faire remarquer, c'est que les trois derniers chiffres restent constants, à savoir 306 à chaque saut. se produit comme indiqué dans l'image suivante.

  2. ce problème se produit lorsque je redémarre mon ordinateur

enter image description here

113
kashif

Vous rencontrez probablement le problème ici (machine de retour).

SQL Server 2012 utilise désormais une taille de cache de 1 000 lors de l'allocation de valeurs IDENTITY dans une colonne int et le redémarrage du service peut "perdre" les valeurs inutilisées (la taille du cache est de 10 000 pour bigint/numeric).

D'après les données que vous avez montrées, il semble que cela se soit passé après la saisie du 22 décembre, puis après le redémarrage, SQL Server a réservé les valeurs 1206306 - 1207305. Après la saisie des données du 24 au 25 décembre, un autre redémarrage a été effectué et SQL Server a réservé la plage suivante 1207306 - 1208305 visible dans les entrées du 28.

À moins que vous ne redémarriez le service à une fréquence inhabituelle, il est peu probable que des valeurs "perdues" fassent une différence significative dans la plage de valeurs autorisée par le type de données. Par conséquent, la meilleure stratégie consiste à ne pas s'en soucier.

Si, pour une raison quelconque, vous rencontrez un problème réel, consultez les solutions de contournement sur le thread lié d'élément de connexion.

  1. Vous pouvez utiliser une SEQUENCE à la place d'une colonne d'identité et définir une taille de cache inférieure, par exemple, et utiliser NEXT VALUE FOR dans une colonne par défaut.
  2. Ou appliquez l'indicateur de trace 272 qui rend l'allocation IDENTITY consignée comme dans les versions précédentes.

Vous devez savoir qu'aucune de ces solutions de rechange ne garantit l'absence de lacunes. Ceci n’a jamais été garanti par IDENTITY car cela n’aurait été possible qu’en sérialisant les insertions dans la table. Si vous avez besoin d'une colonne sans interruption, vous devrez utiliser une solution différente de IDENTITY ou SEQUENCE.

143
Martin Smith

Ce problème se produit après le redémarrage de SQL Server.

La solution est:

  • Exécuter Gestionnaire de configuration SQL Server.

  • Sélectionnez Services SQL Server.

    SQL Server Configuration Manager

  • Cliquez avec le bouton droit de la souris sur SQL Server et sélectionnez Propriétés.

  • Dans la fenêtre qui s'ouvre sous Paramètres de démarrage, tapez -T272 et cliquez sur le bouton Ajouter, puis appuyez sur le bouton Appliquer et redémarrez.

    SQL Server startup parameters

53
Harun ERGUL

Je sais que ma réponse pourrait être en retard à la fête. Mais j'ai résolu le problème d'une autre manière en ajoutant une procédure stockée de démarrage dans SQL Server 2012.

Créez une procédure stockée suivante dans la base de données maître.

USE [master]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER PROCEDURE [dbo].[ResetTableNameIdentityAfterRestart]
AS
BEGIN

begin TRAN
    declare @id int = 0
    SELECT @id =  MAX(id) FROM [DatabaseName].dbo.[TableName]
    --print @id
    DBCC CHECKIDENT ('[DatabaseName].dbo.[TableName]', reseed, @id)
Commit

END

Ajoutez-le ensuite à Démarrer en utilisant la syntaxe suivante.

EXEC sp_procoption 'ResetOrderIdentityAfterRestart', 'startup', 'on';

C'est une bonne idée si vous avez peu de tables. mais si vous devez faire pour beaucoup de tables, cette méthode fonctionne toujours mais pas une bonne idée.

24
Jeyara

De SQL Server 2017+, vous pouvez utiliser ALTER DATABASE SCOPED CONFIGURATION :

IDENTITY_CACHE = {ON | OFF}

Active ou désactive le cache d'identité au niveau de la base de données. La valeur par défaut est ON. La mise en cache d'identité est utilisée pour améliorer les performances INSERT sur les tables comportant des colonnes Identity. Pour éviter les écarts dans les valeurs de la colonne Identity dans les cas de redémarrage inattendu du serveur ou de basculement sur un serveur secondaire, désactivez l'option IDENTITY_CACHE. Cette option est similaire à l'indicateur de trace SQL Server 272 existant, à la différence qu'il peut être défini au niveau de la base de données plutôt que uniquement au niveau du serveur.

(...)

G. Définir IDENTITY_CACHE

Cet exemple désactive le cache d'identité.

ALTER DATABASE SCOPED CONFIGURATION SET IDENTITY_CACHE=OFF ;
24
Lukasz Szozda

Cela reste un problème très courant chez de nombreux développeurs et applications, quelle que soit leur taille.

Malheureusement, les suggestions ci-dessus ne résolvent pas tous les scénarios, à savoir l'hébergement partagé, vous ne pouvez pas compter sur votre hôte pour définir le paramètre de démarrage -t272.

De même, si des tables existantes utilisent ces colonnes d’identité pour les clés primaires, il s’avère très laborieux de supprimer ces colonnes et de en recréer de nouvelles afin d’utiliser la solution de contournement de séquence BS. La solution de contournement Séquence n'est utile que si vous concevez de nouvelles tables dans SQL 2012+.

En bout de ligne, si vous êtes sur Sql Server 2008R2, restez sur ON. Sérieusement, reste dessus. Jusqu'à ce que Microsoft admette avoir introduit un bogue ÉNORME, qui existe toujours, même dans SQL Server 2016, nous ne devrions pas procéder à la mise à niveau tant qu'ils ne le possèdent pas et ne le corrigent pas.

Microsoft a tout de suite introduit un changement radical, c’est-à-dire qu’ils ont cassé une API fonctionnelle qui ne fonctionne plus comme prévu, car son système oublie son identité actuelle lors d’un redémarrage. Cache ou pas de cache, c'est inacceptable, et le développeur Microsoft, sous le nom de Bryan, doit en être le propriétaire, au lieu de dire au monde entier qu'il s'agit "de par sa conception" et d'une "fonctionnalité". Bien sûr, la mise en cache est une fonctionnalité, mais nous ne savons pas ce que devrait être la prochaine identité, IS PAS UNE CARACTÉRISTIQUE. C’est un BUG décoiffant !!!

Je vais partager la solution de contournement que j'ai utilisée, car mes bases de données sont sur des serveurs d'hébergement partagé. En outre, je ne dépose pas et ne recrée pas mes colonnes de clé primaire, ce serait un énorme PITA.

Au lieu de cela, c'est mon bidouillage honteux (mais pas aussi honteux que ce bogue de point de vente que Microsoft a introduit).

Hack/Fix:

Avant vos commandes d'insertion, il suffit de réamorcer votre identité avant chaque insertion. Ce correctif n’est recommandé que si vous n’avez pas le contrôle de votre instance sur votre instance Sql Server, sinon je suggère de réensemencer lors du redémarrage du serveur.

declare @newId int -- where int is the datatype of your PKey or Id column
select @newId = max(YourBuggedIdColumn) from YOUR_TABLE_NAME
DBCC CheckIdent('YOUR_TABLE_NAME', RESEED, @newId)

Juste ces 3 lignes juste avant votre insertion, et vous devriez être prêt à partir. Cela n’affectera vraiment pas beaucoup les performances, c’est-à-dire que cela sera imperceptible.

Bonne chance.

14
green_mystic_Orb

Il y a beaucoup de raisons possibles pour sauter des valeurs d'identité. Ils vont des insertions annulées à la gestion des identités pour la réplication. Qu'est-ce qui cause cela dans votre cas, je ne peux pas le dire sans passer un peu de temps dans votre système.

Vous devez toutefois savoir qu’en aucun cas une colonne d’identité ne peut être contiguë. Trop de choses peuvent créer des lacunes.

Vous pouvez trouver un peu plus d'informations à ce sujet ici: http://sqlity.net/fr/792/the-gap-in-the-identity-value-value-sequence/

7
Sebastian Meine