Приращение личности - это прыжок в базе данных SQL Server

В одной из моих таблиц Fee в столбце "ReceiptNo" в SQL Server 2012 инкремент идентификатора базы данных неожиданно начал переходить на 100 с вместо 1 в зависимости от следующих двух вещей.

  • если он равен 1205446, он переходит на 1206306, если он равен 1206321, он переходит на 1207306, а если он равен 1207314, он перескакивает до 1208306. Я хочу обратить внимание на то, что последние три цифры остаются постоянная, т.е. 306, когда происходит прыжок, как показано на следующем рисунке.

  • эта проблема возникает, когда я перезагружаю компьютер.

enter image description here

Ответ 1

Вероятно, вы столкнулись с проблемой.

В SQL Server 2012 теперь используется размер кеша 1000 при распределении значений IDENTITY в столбце int, и перезапуск службы может "потерять" неиспользуемые значения (размер кеша составляет 10 000 для bigint/numeric).,

Из данных, которые вы показали, похоже, что это произошло после ввода данных 22 декабря, а затем при перезапуске SQL Server зарезервировал значения 1206306 - 1207305. После ввода данных в течение 24-25 декабря был выполнен еще один перезапуск, а SQL Server зарезервировал следующий диапазон 1207306 - 1208305, видимый в записях для 28-го.

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

Если это по какой-то причине является реальной проблемой, вы видите обходные пути связанного потока Connect Item.

  • Вы можете использовать SEQUENCE вместо столбца идентификации и определить, например, меньший размер кеша и использовать NEXT VALUE FOR в столбце по умолчанию.
  • Или применить флаг трассировки 272, который делает распределение IDENTITY зарегистрированным как в предыдущих версиях.

Вы должны знать, что ни одно из этих обходных решений не гарантирует пробелов. Это никогда не гарантировалось IDENTITY, поскольку это было бы возможно только путем сериализации вставок в таблицу. Если вам нужен бесщеточный столбец, вам нужно будет использовать другое решение, чем IDENTITY или SEQUENCE

Ответ 2

Эти проблемы возникают после перезапуска SQL Server.

Решение:

  • Запустите Диспетчер конфигурации SQL Server.

  • Выберите Службы SQL Server.

    SQL Server Configuration Manager

  • Щелкните правой кнопкой мыши SQL Server и выберите Свойства.

  • В открывшемся окне под Параметры запуска введите -T272 и нажмите Добавить, затем нажмите кнопку Применить и перезапустите.

    SQL Server startup parameters

Ответ 3

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

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

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

ALTER PROCEDURE [dbo].[ResetOrderIdentityAfterRestart]
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';

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

Ответ 4

Существует много возможных причин для пересказывания значений идентичности. Они варьируются от откатных вставок до управления идентификацией для репликации. Что вызывает это в вашем случае, я не могу сказать, не потратив некоторое время в вашей системе.

Однако вы должны знать, что вы ни в коем случае не можете считать столбец идентичности конгигуациями. Слишком много вещей, которые могут вызвать пробелы.

Вы можете найти немного больше информации об этом здесь: http://sqlity.net/en/792/the-gap-in-the-identity-value-sequence/

Ответ 5

Это все еще очень распространенная проблема среди многих разработчиков и приложений независимо от размера.

К сожалению, приведенные выше предложения не устраняют все сценарии, то есть общий хостинг, вы не можете полагаться на свой хост, чтобы установить параметр запуска -t272.

Кроме того, если у вас есть существующие таблицы, которые используют эти столбцы идентификации для первичных ключей, это ОГРОМНОЕ усилие, чтобы удалить эти столбцы и воссоздать новые, чтобы использовать обходной путь последовательности BS. Обходной путь Sequence хорош только в том случае, если вы разрабатываете новые таблицы с нуля в SQL 2012 +

Нижняя строка, если вы находитесь на Sql Server 2008R2, затем ОСТАВАЙТЕСЬ НА ЭТО. Серьезно, оставайся на нем. До тех пор пока Microsoft не признает, что они представили HUGE ошибку, которая все еще существует даже на Sql Server 2016, тогда мы не должны обновляться до тех пор, пока они не станут владельцами и не будут исправлены.

Microsoft прямо внедрила переломное изменение, т.е. нарушило рабочий API, который больше не работает так, как было разработано, из-за того, что их система забывает их текущую идентификацию при перезагрузке. Кэш или отсутствие кеша, это неприемлемо, и разработчик Microsoft по имени Брайан должен владеть им, а не говорить миру, что он "по дизайну" и "функции". Конечно, кеширование - это особенность, но потерять следы того, что должно быть следующим идентификатором, НЕ ХАРАКТЕРИСТИКА. Это фрэнк BUG!!!

Я расскажу об обходном пути, который использовал, потому что моя БД находится на серверах с общим хостингом, также я не отбрасываю и не воссоздаю столбцы первичного ключа, это будет огромная PITA.

Вместо этого это мой позорный взлом (но не такой постыдный, как эта ошибка POS, введенная Microsoft).

Hack/Fix:

Перед вашими командами вставки просто добавьте свою личность перед каждой вставкой. Это исправление рекомендуется только в том случае, если у вас нет административного контроля над экземпляром Sql-сервера, в противном случае я предлагаю повторно выполнить перезагрузку сервера.

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)

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

Гудлак.

Ответ 6

От SQL Server 2017+ вы можете использовать ALTER DATABASE SCOPED CONFIGURATION:

IDENTITY_CACHE = {ON | ВЫКЛ}

Включение или отключение кеша идентификации на уровне базы данных. По умолчанию ВКЛЮЧЕН. Кэширование идентичности используется для улучшения производительности INSERT на таблицы с колонками Identity. Чтобы избежать пробелов в значениях Столбец идентификатора в случаях, когда сервер неожиданно перезапускается или не удается перейти на вторичный сервер, отключите параметр IDENTITY_CACHE.Этот параметр похож на существующий SQL Server Trace Flag 272, за исключением того, что он может быть установлен на уровне базы данных, а не только на уровень сервера.

(...)

G. Установите IDENTITY_CACHE

В этом примере отключается кеш идентификатора.

ALTER DATABASE SCOPED CONFIGURATION SET IDENTITY_CACHE=OFF ;