Столбец первичного ключа увеличивается на неправильное значение приращения - PullRequest
1 голос
/ 04 марта 2020

У меня странная проблема с таблицами в моей базе данных. Таблицы в моем приложении создаются с определением первичного ключа (с кластеризованным индексом). Идентификационное начальное число является единым для всех таблиц в моей базе данных (IDENTITY (1,1)).

В этих базах данных выполняются операции CRUD с использованием хранимых процедур, которые вызываются из приложения ADO. net windows , Проблема, с которой я здесь сталкиваюсь, заключается в том, что иногда значения первичного ключа увеличиваются на 1000 или 10000, и я не могу понять, почему. Вот несколько таблиц для Ex. здесь после значений 170142, 180141 используется сервером SQL или когда-то после того, как 5025 значений первичного ключа 6025 выбирается с помощью SQL

170139
170140
170141
170142
180141
180142
180143
180144
190141
190142
190143
190144

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

Кто-нибудь сталкивался с подобным сценарием ios? Ваша помощь очень ценится.

Ответы [ 2 ]

3 голосов
/ 04 марта 2020

То, что вы видите, может быть SQL Значения идентификаторов кэширования сервера по соображениям производительности. При вставке большого количества строк в майские сеансы столбец идентификаторов может стать узким местом.

Чтобы уменьшить конфликт, SQL Сервер резервирует большое количество первичных ключей в памяти - например, 10 000. Управлять этими кэшированными значениями идентификаторов намного быстрее, чем сохранять новое значение следующего идентификатора после каждой вставки. Недостатком является то, что перезагрузка или перезапуск службы может привести к большим пробелам в значениях первичного ключа.

Обратите внимание, что столбец идентификаторов не гарантирует монотонно увеличивающееся значение :

Свойство identity в столбце не гарантирует следующее:

  • Уникальность значения - Уникальность должна быть обеспечена с помощью PRIMARY KEY или UNIQUE ограничение или УНИКАЛЬНЫЙ индекс.

  • Последовательные значения в транзакции - Транзакция, вставляющая несколько строк, не гарантирует получение последовательных значений для строк, поскольку могут происходить другие параллельные вставки на столе. Если значения должны быть последовательными, то транзакция должна использовать монопольную блокировку таблицы или уровень изоляции SERIALIZABLE.

  • Последовательные значения после перезапуска сервера или других сбоев - SQL Сервер может кэшировать значения идентификаторов по соображениям производительности, и некоторые из назначенных значений могут быть потеряны во время сбоя базы данных или перезапуска сервера. Это может привести к пробелам в значении идентичности при вставке. Если пропуски неприемлемы, приложение должно использовать свой собственный механизм для генерации значений ключей. Использование генератора последовательности с опцией NOCACHE может ограничить пропуски транзакциями, которые никогда не фиксируются.

  • Повторное использование значений - Для заданного свойства идентификатора с определенным начальным значением / инкремент, значения идентичности не используются повторно двигателем. Если конкретный оператор вставки завершается неудачно или если оператор вставки откатывается, то использованные значения идентификаторов теряются и больше не генерируются. Это может привести к появлению пропусков при создании последующих значений идентификаторов.

Другая возможность - откаты. Откат вставки из 1000 строк будет использовать до 1000 ключевых значений. Эти неиспользуемые значения ключей будут отображаться как пробел в первичных ключах.

Удаление также может привести к большим пробелам.

3 голосов
/ 04 марта 2020

Никогда не видел и не слышал об этом как о проблеме: и SQL Поля идентичности используются так часто, что я почти уверен, что они появятся.

Вы уверены, что это именно то, что происходит? Было бы легко увидеть такие изменения, например, если строки будут удалены, поскольку значения идентификаторов не будут использоваться повторно. Вставьте 5 строк:

INSERT INTO MyTable (desc) VALUES ('One') ('Two') ('Three') ('Four') ('Five')

Дает вам:

1 One
2 Two
3 Three
4 Four
5 Five

Затем удалите пару:

DELETE FROM MyTable WHERE id IN (2, 4, 5)

И добавьте еще пару:

INSERT INTO MyTable (desc) VALUES ('New') ('And again')

И вы получите:

1 One
3 Three
6 New
7 And again

для лучшего понимания

...