Столбец идентичности SQL вышел из шага - PullRequest
2 голосов
/ 09 января 2009

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

Таким образом, таблица в DB1 будет генерировать 30001, 30051 и т. Д., Где Database2 будет генерировать 30002, 30052 и т. Д.

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

Мне, очевидно, придется как-то обойти эту проблему (возможно, установив высокое начальное значение), но кто-нибудь может сказать мне, что может привести к такой синхронизации? Из запроса к БД я вижу, что последовательность пошла следующим образом: 32403, 32453, 32456, 32474, 32524, 32574 и продолжалась с шагом 50 с тех пор, как произошла ошибка.

Насколько мне известно, ни одна массовая вставка, ни DTS, ни что-либо подобное не добавили новые данные в эти таблицы.

Второй (бонусный) вопрос - как сбросить личность так, чтобы она возвращалась к тому, кем я хочу быть на самом деле!

EDIT:

Я знаю, что дизайн в принципе немного странный - я не просил критиковать его, я просто удивлялся, как он мог выйти из-под контроля. Я унаследовал эту систему, и изменение столбца на GUID - хотя, несомненно, лучшее теоретическое решение - вероятно, не произойдет. Система превратилась из одной БД в несколько БД, когда нагрузка стала слишком большой (в настоящее время несколько сотен ГБ). На каждый идентификатор в этой таблице будут ссылаться во многих других местах - иногда по несколько сотен тысяч раз каждый (умноженный примерно на 40000 для каждого элемента). Обновления всего этого не будет; -)

Ответы [ 6 ]

2 голосов
/ 09 января 2009

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

Если вы хотите объединить строки из нескольких таблиц, то вы нарушаете намерение Identity, которое относится к одной таблице. (В столбце GUID будут использоваться значения, достаточно уникальные для решения этой проблемы. Но вы все равно не можете придать им значимое значение.)

2 голосов
/ 09 января 2009

Репликация = столбец GUID.

Чтобы установить значение следующего идентификатора равным 1000:

DBCC CHECKIDENT (orders, RESEED, 999)
1 голос
/ 09 января 2009

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

При репликации вам действительно нужно идентифицировать ваши данные с помощью GUID. Вероятно, вам будет легче перенести ваши данные в схему, которая использует идентификаторы GUID для ПК, чем пытаться разобраться с проблемами IDENTITY.

1 голос
/ 09 января 2009

Возможно, кто-то использовал:

SET IDENTITY INSERT {tablename} ON

INSERT INTO {tablename} (ID, ...)
VALUES(32456, ....)

SET IDENTITY INSERT {tablename} OFF

Или, возможно, они использовали DBCC CHECKIDENT для изменения личности. В любом случае, вы можете использовать то же самое, чтобы установить его обратно.

0 голосов
/ 24 февраля 2010

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

Hi_lo используется ORM nhibernate, но я не смог найти много документации по нему.

По сути, Hi_lo работает так, что у вас есть 1 центральное место, где вы отслеживаете значение hi. 1 таблица в 1 из баз данных, которую может видеть каждый экземпляр вашего приложения вставки. тогда вам нужен какой-то сервис (объект, веб-сервис и т. д.), у которого срок службы несколько больше, чем у одной вставки. этот сервис при запуске перейдет в таблицу hi, возьмет текущее значение и увеличит значение в этой таблице. Для этого используйте блокировку на чтение, чтобы не было проблем с параллелизмом с другими экземплярами службы. Теперь вы будете использовать новый сервис для получения вашего следующего значения идентификатора. Он внутренне начинается с числа, полученного из БД, и когда он передает это значение, увеличивается на 1., отслеживая это текущее значение и «диапазон», который ему разрешено пропускать. Вот упрощенный пример:

  1. сервис 1 получает 100 из таблицы "hi_value" в дБ. увеличивает значение в 200 дБ.
  2. служба 1 получает запрос на новый идентификатор. вырубается 100.
  3. другой экземпляр службы, служба 2 (либо другой поток, другая рабочая машина среднего уровня и т. Д.) Раскручивается, получает 200 из БД, увеличивает значение БД до 300.
  4. служба 2 получает запрос на новый идентификатор. проходит 200.
  5. служба 1 получает запрос на новый идентификатор. вырубается 101. если какой-либо из них когда-либо потеряет больше 100, прежде чем умереть, он вернется к БД, получит текущее значение, увеличит его и начнет все сначала. Очевидно, в этом есть какое-то искусство. Насколько большим должен быть ваш диапазон и т. Д.

Очень простой вариант - это одна таблица в одной из ваших БД, которая просто содержит значение "nextId". в основном, вручную воспроизводит концепцию последовательности оракула. ​​

0 голосов
/ 10 января 2009

Чтобы ответить на ваш вопрос напрямую,

  1. Почему это вышло из-под контроля, может быть интересно обсудить, но единственный результат, который вы могли бы извлечь из ответа, - это предотвратить его в будущем; что плохой курс действий. У вас останутся эти и более серьезные проблемы, если вы не столкнетесь с дизайном, имеющим роковой недостаток.

  2. Как правильно настроить существующие значения - это тоже (ИМХО) недопустимый вопрос, потому что вам нужно сделать что-то, кроме правильного задания значений - это не решит вашу проблему.

Это не для того, чтобы унизить вас, а для того, чтобы помочь вам наилучшим образом, о чем я могу думать. Смена дизайна - это меньше работы, как краткосрочной, так и долгосрочной. Не менять дизайн - это путь к FAIL.

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