SQL Identity (autonumber) добавляется даже с откатом транзакции

У меня есть транзакция .net с вставкой SQL в базу данных SQL Server 2005. Таблица имеет первичный ключ идентификации.

Когда в транзакции возникает ошибка, вызывается Rollback(). Вставки строк возвращаются правильно, однако в следующий раз, когда я вставляю данные в таблицу, идентификатор увеличивается, как если бы откат никогда не происходил. Таким образом, по существу существуют пробелы в последовательности идентичности. Есть ли способ, чтобы метод Rollback() возвращал отсутствующий идентификатор?

Я не подхожу к этому правильно?

Ответ 1

Если вы думаете об этом, номер автоматического увеличения не должен быть транзакционным. Если другим транзакциям приходилось ждать, будет ли использоваться автоматический номер или "откат", они будут заблокированы существующей транзакцией с использованием автоматического номера. Например, рассмотрим мой код psuedo ниже с таблицей A, используя поле автоматического номера для столбца ID:

User 1
------------
begin transaction
insert into A ...
insert into B ...
update C ...
insert into D ...
commit


User 2
-----------
begin transaction
insert into A ...
insert into B ...
commit

Если транзакция пользователя 2 начинается с миллисекунды после пользователя 1, тогда их вставка в таблицу A должна будет дождаться завершения всей транзакции пользователя 1, чтобы увидеть, был ли использован автоматический номер из первой вставки в A.

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

Ответ 2

Если вы зависите от того, что ваши идентификационные данные являются бесщелевыми, то да - вы делаете это неправильно. Весь смысл суррогатного ключа состоит в том, чтобы не иметь делового смысла.

И нет, нет никакого способа изменить это поведение (не дожидаясь перескакивания собственного автоинкремента и страдания от последствий производительности блокировки других вставок).

Ответ 3

Вы получаете пробелы в своей последовательности, если вы DELETE тоже.

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

Ответ 4

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

Ответ 5

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

  • транзакция a начинается и вставляет
  • транзакция b начинается и вставляет
  • транзакция отменяет

    вы получите отверстие. нечего делать.

Ответ 6

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

FYI, если по какой-либо причине вы хотите удалить пробелы, большинство баз данных имеют способ перенастроить автоматическую нумерацию на номер по вашему выбору. Это боль в заднице, и если вам нужно регулярно делать это, вам определенно не следует использовать поле autonumber/identity, как указано выше. Но вот код для этого в SQL-сервере:

DBCC CHECKIDENT ( "Продукт", RESEED, 0)

Это устанавливает, что таблица продуктов начинается с 1 (хотя, если у вас есть записи в таблице, она, очевидно, пропустит уже сделанные идентификационные значения.) У других производителей RDBMS есть свой собственный синтаксис, но эффект примерно то же самое, так что посмотрите "reseed identity" или "resed autonumber" в файлах или интервалах системной справки.

Опять же: это для особых случаев, а не для регулярного использования. Не ставьте его в хранимую процедуру и заставляйте всех нас приходить.

Ответ 7

Мухан пытается подумать об этом в контексте многих одновременных подключений, выполняющих эту транзакцию, а не по одному за раз. Некоторые потерпят неудачу, а некоторые преуспеют. Вы хотите, чтобы SQL Server сконцентрировался на запуске новых запросов по мере их поступления, а не на поддержании столбца идентификации без пробелов. ИМО это (пробелы в значениях), безусловно, не стоит тратить время.

Ответ 8

Нет. Применения последовательностей используют автономную транзакцию. В Oracle автономная транзакция была когда-то внутренней для dbms, но теперь отображается для вашего собственного использования (и часто используется неправильно)

PRAGMA AUTONOMOUS_TRANSACTION;'