web-dev-qa-db-fra.com

Incrément d'identité de colonne SQL Server 2012 passant de 6 à 1 000+ à la 7e entrée

J'ai un scénario étrange dans lequel la colonne auto identity int de ma base de données SQL Server 2012 ne s'incrémente pas correctement.

Supposons que j'ai une table qui utilise une identité automatique auto comme clé primaire. Elle saute sporadiquement des incréments, par exemple:

1, 2, 3, 4, 5, 1004, 1005

Cela se produit sur un nombre aléatoire de tables à des moments très aléatoires, vous ne pouvez pas le reproduire pour trouver des tendances.

Comment ça se passe? Y a-t-il un moyen d'arrêter ça?

121
Andy Clark

Tout cela est parfaitement normal. Microsoft a ajouté sequences dans SQL Server 2012. Enfin, je pourrais éventuellement ajouter et modifier la manière dont les clés d'identité sont générées. Regardez ici pour une explication.

Si vous voulez avoir l'ancien comportement, vous pouvez:

  1. utiliser l'indicateur de trace 272 - un enregistrement de journal sera généré pour chaque valeur d'identité générée. La performance de la génération d’identité peut être affectée par l’activation de cet indicateur de trace.
  2. utiliser un générateur de séquence avec le paramètre NO CACHE ( http://msdn.Microsoft.com/en-us/library/ff878091.aspx )
75
Mithrandir

A obtenu le même problème, trouvé le rapport de bogue suivant dans SQL Server 2012 Si toujours pertinent, voir les conditions qui causent le problème - il existe également des solutions de contournement (je n'ai pas essayé cependant). le basculement ou le redémarrage a pour résultat une nouvelle identité

4
yoosha

Bien que l’indicateur de trace 272 puisse fonctionner pour beaucoup, il ne fonctionnera certainement pas pour les installations hébergées Sql Server Express. J'ai donc créé une table d'identité et je l'ai utilisé via un déclencheur INSTEAD OF. J'espère que cela aidera quelqu'un d'autre et/ou donnera aux autres l'occasion d'améliorer ma solution. La dernière ligne permet de retourner la dernière colonne d'identité ajoutée. Étant donné que j'utilise généralement ceci pour ajouter une seule ligne, cela permet de renvoyer l'identité d'une seule ligne insérée.

La table d'identité:

CREATE TABLE [dbo].[tblsysIdentities](
[intTableId] [int] NOT NULL,
[intIdentityLast] [int] NOT NULL,
[strTable] [varchar](100) NOT NULL,
[tsConcurrency] [timestamp] NULL,
CONSTRAINT [PK_tblsysIdentities] PRIMARY KEY CLUSTERED 
(
    [intTableId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF,  ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

et le déclencheur d'insertion:

-- INSERT --
IF OBJECT_ID ('dbo.trgtblsysTrackerMessagesIdentity', 'TR') IS NOT NULL
   DROP TRIGGER dbo.trgtblsysTrackerMessagesIdentity;
GO
CREATE TRIGGER trgtblsysTrackerMessagesIdentity
ON dbo.tblsysTrackerMessages
INSTEAD OF INSERT AS 
BEGIN
    DECLARE @intTrackerMessageId INT
    DECLARE @intRowCount INT

    SET @intRowCount = (SELECT COUNT(*) FROM INSERTED)

    SET @intTrackerMessageId = (SELECT intIdentityLast FROM tblsysIdentities WHERE intTableId=1)
    UPDATE tblsysIdentities SET intIdentityLast = @intTrackerMessageId + @intRowCount WHERE intTableId=1

    INSERT INTO tblsysTrackerMessages( 
    [intTrackerMessageId],
    [intTrackerId],
    [strMessage],
    [intTrackerMessageTypeId],
    [datCreated],
    [strCreatedBy])
    SELECT @intTrackerMessageId + ROW_NUMBER() OVER (ORDER BY [datCreated]) AS [intTrackerMessageId], 
    [intTrackerId],
   [strMessage],
   [intTrackerMessageTypeId],
   [datCreated],
   [strCreatedBy] FROM INSERTED;

   SELECT TOP 1 @intTrackerMessageId + @intRowCount FROM INSERTED;
END