2013-08-26 7 views
9

Мы работаем SQL Server 2012 SP1 x64 (11.0.3000.0)SQL Server: произвольное автоматическое приращение первичного ключа

У меня есть следующая таблица с InvoiceId поля как автоинкрементные, первичный ключом:

CREATE TABLE Orders(
    InvoiceId   bigint   IDENTITY(1001,1) NOT FOR REPLICATION, 
    OrderId    varchar(8)  NOT NULL, 
    ... -- other fields removed for brevity 
    CONSTRAINT [PK_ORDERS] PRIMARY KEY CLUSTERED (InvoiceId) 
    ON [PRIMARY], 
) 

Новые строки вставляются, хотя простой хранимой процедуры, как следующее:

SET XACT_ABORT ON 
SET NOCOUNT ON 

BEGIN TRANSACTION 
    INSERT INTO Orders(
      OrderId, 
      ... -- other fields removed for brevity 
     ) 
    VALUES (
      @orderId, 
      ... 
     )    

    SELECT @newRowId = SCOPE_IDENTITY() 
COMMIT TRANSACTION 

выше sproc возвращает вновь созданную строку-идентификатор (Orders.InvoiceId) вызывающему абоненту.

Код работал отлично, с [InvoiceId] начиная с 1001 и увеличивая на 1 для каждой последовательной вставки.

Наши пользователи вставили около 130 рядов. [InvoiceId] был на 1130, затем на следующей вставке его значение подскочило до !

Вот скриншот данные:

data

Я сбит с толку, как к тому, что только что произошло здесь. Почему автоматический счетчик неожиданно пропустил почти 10 000 очков?

Мы используем значение [InvoiceId] для генерации штрих-кодов, поэтому мы предпочли бы, чтобы значение оставалось в определенном диапазоне, предпочтительно в непрерывной серии.

Я просмотрел документацию T-SQL, но не смог найти что-либо, связанное с моей проблемой. Является ли это обычным поведением (произвольная популяция) поля идентичности?

ОБНОВЛЕНИЕ Благодаря Marting & Aron, я нашел обход. Вот official response от Microsoft:

В SQL Server 2012 реализация имущества идентичности была была изменена для размещения инвестиций в другие функции. В предыдущих версиях SQL Server отслеживание генерации идентичности ссылалось на записи журнала транзакций для каждого генерируемого значения. В SQL Server 2012 мы генерируем идентификационные значения в партиях и регистрируем только максимальное значение партии. Это уменьшает количество и частоту информации, записанной в журнал транзакций, улучшая вставку масштабируемость.

Если требуются те же семантику поколения идентичности, как и предыдущие версии SQL Server есть два доступных опций:

• Используйте флаг трассировки 272 о Это приведет к записи журнала, которые будут созданы для каждого генерируемой идентичности стоимость. Эффективность генерации идентичности может быть вызвана включением этого флага трассировки.

• использовать последовательность генератора с NO CACHE настройки (http://msdn.microsoft.com/en-us/library/ff878091.aspx) O Эта вызовет запись журнала, которые будут созданы для каждого генерируемого значения последовательности . Обратите внимание, что производительность генерации значения последовательности может быть , на которую воздействует NO CACHE.

Пример:

CREATE SEQUENCE s1 AS INT START WITH 1 NO CACHE; 
CREATE TABLE t1 (Id INT PRIMARY KEY DEFAULT NEXT VALUE FOR s1, col INT NOT NULL); 
+5

'IDENTITY' никогда не гарантируется непрерывным, но есть известная проблема, в 2012 году, где она может внезапно перепрыгнуть оставляя большие пробелы после перезапуска службы. –

+0

Спасибо @MartinSmith! Кажется, это проблема в моем случае. Я помню, как перезагружал машину db до того, как ускорился приращение личности! Как я могу избежать этого? – masroore

+1

Вы не можете избежать этого наверняка, поскольку соприкосновение никогда не гарантировалось, но есть флаг трассировки, который вы можете установить, чтобы получить более медленное (зарегистрированное) поведение 2008 года, или вы можете использовать последовательность с меньшим размером кеша. См. [Обсуждение здесь] (https://connect.microsoft.com/SQLServer/feedback/details/739013/failover-or-restart-results-in-reseed-of-identity) –

ответ

2

UPDATE Благодаря Marting & Aron, я нашел обход. Вот официальный ответ от Microsoft:

В SQL Server 2012 реализация свойства идентификации была изменена для учета инвестиций в другие функции. В предыдущих версиях SQL Server отслеживание генерации идентификаторов зависело от записей журнала транзакций для каждого генерируемого значения идентификации. В SQL Server 2012 мы генерируем идентификационные значения в партиях и регистрируем только максимальное значение пакета. Это уменьшает количество и частоту информации, записанной в журнал транзакций, улучшая масштабируемость вставки.

Если требуются те же семантику поколения идентичности как в предыдущих версиях SQL Server есть две опции:

• Используйте флаг трассировки 272 O Это приведет к записи журнала, которые будут созданы для каждого сгенерированного значения идентичности. На производительность генерации идентификаторов может повлиять включение этого флага трассировки.

• Используйте генератор последовательности с установкой NO CACHE (http://msdn.microsoft.com/en-us/library/ff878091.aspx) o Это приведет к созданию записи журнала для каждого генерируемого значения последовательности. Обратите внимание, что на производительность генерации значений последовательности может влиять использование NO CACHE.

Пример:

CREATE SEQUENCE s1 AS INT START WITH 1 NO CACHE; 
CREATE TABLE t1 (Id INT PRIMARY KEY DEFAULT NEXT VALUE FOR s1, col INT NOT NULL); 
0

В качестве альтернативы, вы можете иметь специальную таблицу с прилавков. Это не хороший дизайн, но он поставил вас в полный контроль над тем, как работает идентификация.

Смежные вопросы