SQL Server 2012 приращение идентификатора столбца прыгает с 6 до 1000+ на 7-й записи [дубликат]


этот вопрос уже есть ответ здесь:

У меня есть странный сценарий, в котором столбец auto identity int в моей базе данных SQL Server 2012 не увеличивается должным образом.

скажем, у меня есть таблица, которая использует int auto identity в качестве первичный ключ это спорадически пропуская приращения, например:

1, Два, Три, Четыре, Пять, Одна тысяча четыре, 1005

Это происходит на случайном количестве таблиц в очень случайные моменты времени, не может повторить его, чтобы найти какие-либо тенденции.

Как это происходит? Есть ли способ остановить это?

4 108

4 ответа:

Это все совершенно нормально. Microsoft добавила sequences в SQL Server 2012, наконец, я мог бы добавить и изменить способ создания ключей идентификации. Посмотри здесь для некоторого объяснения.

Если вы хотите иметь старое поведение, вы можете:

  1. использовать флаг трассировки 272-это приведет к созданию записи журнала для каждого сгенерированного значения идентификатора. Включение этой трассировки может повлиять на производительность генерации идентификаторов флаг.
  2. используйте генератор последовательностей с параметром no CACHE (http://msdn.microsoft.com/en-us/library/ff878091.aspx)

Я знаю, что мой ответ может опоздать на вечеринку. Но я решил по-другому, добавив хранимую процедуру запуска в SQL Server 2012.

создайте следующую хранимую процедуру в главной БД.

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

затем добавьте его для запуска, используя следующий синтаксис.

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

Это хорошая идея, если у вас есть несколько таблиц. но если вам нужно сделать много таблиц, этот способ все еще работает, но не очень хорошая идея.

получил ту же проблему, нашел следующий отчет об ошибке в SQL Server 2012 Если все еще актуальны условия, которые вызывают проблему-есть некоторые обходные пути там, а также (не пробовал, хотя). отказоустойчивость или перезапуск приводит к повторному заполнению идентификатора

хотя флаг трассировки 272 может работать для многих, он определенно не будет работать для размещенных установок SQL Server Express. Итак, я создал таблицу идентификаторов и использовал ее через триггер INSTEAD OF. Я надеюсь, что это поможет кому-то еще, и/или дает другим возможность улучшить мое решение. Последняя строка позволяет вернуть последний добавленный столбец идентификаторов. Поскольку я обычно использую это для добавления одной строки, это работает для возврата идентификатора одной вставленной строки.

личность таблица:

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]

и вставить триггер:

-- 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