Идентичность SQL (autonumber) увеличивается даже при откате транзакции - PullRequest
73 голосов
/ 12 ноября 2008

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

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

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

Ответы [ 8 ]

97 голосов
/ 12 ноября 2008

Если подумать, номер автоинкремента не должен быть транзакционным. Если другие транзакции должны были ждать, чтобы увидеть, будет ли использоваться автоматический номер или «откатан», они будут заблокированы существующей транзакцией с использованием автоматического номера. Например, рассмотрим мой псевдо-код, приведенный ниже, с таблицей A, в которой используется поле автоматического номера для столбца идентификатора:

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. *

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

31 голосов
/ 12 ноября 2008

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

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

15 голосов
/ 12 ноября 2008

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

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

6 голосов
/ 14 ноября 2008

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

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

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

Это устанавливает таблицу продукта для начала с 1 (хотя, если у вас есть записи в таблице, она, очевидно, пропустит значения идентификаторов, которые уже приняты.) Другие поставщики СУБД имеют собственный синтаксис, но эффект примерно то же самое, поэтому ищите «идентификатор заново» или «номер автозапуска» в файлах справки системы или в интернете.

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

6 голосов
/ 12 ноября 2008

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

4 голосов
/ 12 ноября 2008

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

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

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

1 голос
/ 12 ноября 2008

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

PRAGMA AUTONOMOUS_TRANSACTION;' 
1 голос
/ 12 ноября 2008

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...