SQL Server гарантирует последовательную вставку столбца идентификационных данных?

Другими словами, следующий подход "cursoring", который, как гарантируют, будет работать:

  1. получите строки от DB
  2. сохраните самый большой идентификатор от возвращенных записей на потом, например, в LastMax
  3. позже, "SELECT * FROM MyTable WHERE Id > {0}", LastMax

Для этого для работы я должен быть уверен, что каждая строка, я не вошел в шаг 1, имеет идентификатор, больше, чем LastMax. Это гарантируется, или я могу столкнуться со странными условиями состязания?

13
задан Patrick Karcher 13 May 2010 в 18:55
поделиться

5 ответов

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

  1. Кто-то отключает вставку идентификатора и вставляет значение.
  2. Кто-то повторно заполняет столбец идентичности.
  3. Кто-то меняет знак значения приращения (т.е. вместо +1 он изменяется на -1)

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

  1. Откройте транзакцию, вставьте в свою таблицу столбец идентификаторов. Допустим, он получает значение 42.
  2. Вставить и зафиксировать в той же таблице другое значение. Скажем, он получает значение 43.

Пока первая транзакция не зафиксирована, 43 существует, а 42 - нет. Столбец идентификаторов просто резервирует значение, а не определяет порядок коммитов.

18
ответ дан 1 December 2019 в 21:37
поделиться

Единственный раз, когда могут быть вставлены записи, которые вы не получите, это если кто-то включит идентификационную вставку и вставит вручную запись с пропущенным идентификатором (или в некоторых случаях с отрицательным числом). Это довольно редкое явление и обычно выполняется только системным администратором. Это может быть сделано, например, для повторной вставки случайно удаленной записи.

1
ответ дан 1 December 2019 в 21:37
поделиться

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

  1. Транзакция A начинается
  2. Транзакция A выполняет вставку - это создает новую запись в столбце идентификаторов
  3. Транзакция B начинается
  4. Транзакция B выполняет вставку - это создает новую запись в столбец идентификаторов
  5. Транзакция B фиксируется
  6. Ваш код выполняет свой выбор и видит значение идентичности из 2-й транзакции
  7. Транзакция A фиксируется -

Строка, вставленная транзакцией A, никогда не будет найдена вашим кодом. На момент выполнения шага 6 это еще не было зафиксировано. И когда будет выполнен следующий запрос, он не будет найден, потому что он имеет более низкое значение в столбце идентификаторов, чем ищет запрос.

Это может сработать, если вы выполните запрос в режиме изоляции чтение без фиксации

4
ответ дан 1 December 2019 в 21:37
поделиться

Единственное, что гарантирует SQL Server, - это то, что ваш столбец IDENTITY всегда будет увеличиваться.

Однако на что следует обратить внимание:

  1. Если произойдет сбой INSERT, столбец IDENTITY все равно будет увеличен;
  2. Если произойдет откат, столбец IDENTITY не вернется к своему предыдущему значению;

Что объясняет, почему SQL Server не гарантирует последовательную НЕПРЕРЫВНОСТЬ.

Существует способ сбросить подобный столбец IDENTITY с помощью команды DBCC . Но перед этим учтите следующее:

  1. Убедитесь, что на ваш столбец IDENTITY не ссылается какая-либо другая таблица, поскольку ваши внешние ключи не могут быть обновлены с его помощью, так что впереди большие проблемы;
  2. Вы можете использовать ] SET IDENTITY_INSERT ON / OFF , чтобы вы могли вручную указать IDENTITY при ВСТАВКЕ строки (никогда не забудьте включить ее после).

Столбец IDENTITY - один из самых важных элементов, которые нельзя изменять в DBRM.

Вот ссылка, которая должна вам помочь: Общие сведения о столбцах IDENTITY

EDIT: То, что вы делаете, должно работать, поскольку столбец IDENTITY из LastMax всегда будет увеличиваться для каждой вставленной строки. Итак:

  1. Выбор строк из таблицы данных;
  2. Сохранение состояния LastMax;
  3. Выбор строк, где Id> LastMax.

3) будут выбирать только строки, в которых столбец IDENTITY будет больше, чем LastMax, поэтому вставлен после сохранения LastMax.

0
ответ дан 1 December 2019 в 21:37
поделиться

Идентификаторы всегда будут следовать инкременту, который определяет идентификатор:

IDENTITY [(seed ,increment)] http://msdn.microsoft.com/en-us/library/aa933196(SQL.80).aspx

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

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

2
ответ дан 1 December 2019 в 21:37
поделиться
Другие вопросы по тегам:

Похожие вопросы: