![Столбец идентификатора Bigint подскакивает с 17 до 1004. Почему?](https://rvso.com/image/1595517/%D0%A1%D1%82%D0%BE%D0%BB%D0%B1%D0%B5%D1%86%20%D0%B8%D0%B4%D0%B5%D0%BD%D1%82%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%82%D0%BE%D1%80%D0%B0%20Bigint%20%D0%BF%D0%BE%D0%B4%D1%81%D0%BA%D0%B0%D0%BA%D0%B8%D0%B2%D0%B0%D0%B5%D1%82%20%D1%81%2017%20%D0%B4%D0%BE%201004.%20%D0%9F%D0%BE%D1%87%D0%B5%D0%BC%D1%83%3F.png)
Я использую столбцы bigint identity в нескольких таблицах и замечаю, что они продолжают прыгать от низких чисел к высоким. В этом случае от 17 до 1004, но в других таблицах до 10000. Если это поведение продолжится, я буду в пределах bigint в пределах нескольких тысяч записей! Почему это происходит и как это исправить?
Скриншот здесь:
решение1
Bigint варьируется от -9 223 372 036 854 775 808 до 9 223 372 036 854 775 807. Я думаю, у вас есть время, прежде чем вы достигнете верхних границ - даже если вы прыгаете на 100 тыс. записей за раз, вы можете сделать миллиард прыжков и все равно не достичь верхних границ. Если вы все еще обеспокоены, пересейте свою личность, чтобы начать с отрицательного диапазона, и мы все умрем прежде, чем вам придется беспокоиться о вещах.
Почему в значении идентичности есть пробелы?
Приложение пытается вставить запись в вашу таблицу, и число удаляется из пула. По причинам ссылочной целостности вставка не удается или вызывающая программа затем отменяет (откатывает) транзакционную вставку — в любом случае значение идентификатора больше не находится в пуле кандидатов. Да, даже если транзакция откатывается, число исчерпывается и не откатывается.
Проверьте сами
SET NOCOUNT ON;
IF OBJECT_ID('tempdb..#Demo') IS NOT NULL
BEGIN
DROP TABLE #Demo;
END
CREATE TABLE #Demo
(
demoid int IDENTITY(1,1) NOT NULL
, CantBeNull varchar(50) NOT NULL
);
-- add a record and look at our identity
INSERT INTO #Demo
(CantBeNull)
VALUES
('First Entry');
SELECT SCOPE_IDENTITY() AS GeneratedId;
-- GO forces the batch to commit (assuming default implicit transaction model)
GO
-- Violate RI
INSERT INTO #Demo
(CantBeNull)
VALUES
(NULL);
SELECT SCOPE_IDENTITY() AS RIViolationGeneratedId;
GO
-- add a record and look at our identity
INSERT INTO #Demo
(CantBeNull)
VALUES
('Third Entry');
SELECT SCOPE_IDENTITY() AS ThirdGeneratedId;
GO
-- Transaction consumes
BEGIN TRAN
INSERT INTO #Demo
(CantBeNull)
VALUES
('Fourth Entry');
SELECT SCOPE_IDENTITY() AS FourthGeneratedId;
ROLLBACK;
INSERT INTO #Demo
(CantBeNull)
VALUES
('Fifth Entry');
SELECT SCOPE_IDENTITY() AS FifthGeneratedId;
GO
SELECT D.* FROM #Demo AS D;
На вкладке результатов вы увидите 1, 1, 3, 4 и 5, поскольку именно эти числа использовались, но поскольку мы откатываемся на 4, зафиксированные результаты таблицы #Demo будут выглядеть
demoid CantBeNull
1 First Entry
3 Third Entry
5 Fifth Entry
Мне не нравится такое поведение.
Вот как работает свойство identity — нет способа его изменить. То же самое справедливо, если вы переключитесь на объект Sequence (новый в 2012 году).
Если пробелы вызывают беспокойство, я бы посмотрел на определение того, какой процесс их потребляет. Если это нарушения ссылочной целостности (RI), ужесточите проверку перед попыткой сохранения. Если первопричина в откате транзакций, то сделайте это двухфазным подтверждением или чем-то вроде этого — сохраните в Stage.MyTable. Если проблема в исчерпании идентификаторов, переключитесь на объект SEQUENCE и включите цикличность. Периодически опрашивайте эту таблицу на предмет подтвержденных транзакций, а затем вставляйте в dbo.MyTable оттуда. Это должно уменьшить вероятность существования пробелов в вашем суррогатном ключе.
Кендра Литтлпрекрасный плакат с уровнем изоляции помогает мне помнить, какой уровень изоляции мне нужен для проверки того, что действительно, действительно выполнено.