2013-09-07 2 views
0

У нас есть требование, в котором говорится, что когда мы получаем нового человека в базу данных, нам нужно присвоить им уникальный номер. Это число начнется с определенного номера, когда система войдет в актив. Итак, если клиент скажет: «Начните с 500 000!», Тогда первый выделенный идентификатор будет 500000.Обращение с добавочным номером с помощью DB

Easy - Auto increment fiend.

Однако ID является Account Number, который отправляется внешнему клиенту для связывания человека с учетной записью. Возможно, идея заключалась в использовании первичного ключа auto inc, но я считаю, что плохо использовать ПК в качестве внешнего лица «номер человека».

Кто-то упомянул о наличии таблицы с auto inc pk и идентификатором таблицы лиц, к которому мы добавляем номер. Но это кажется странным.

Моя идея - добавить новый столбец в нашу таблицу settings, которая действительно имеет только одну строку и содержит системные настройки для системы. Столбец будет INT и будет называться NextAvailableId. Все строки имеют столбец Version, который является Timestamp (RowVersion).

Мой план создать функцию под названием GetNextId или что-то, что бы просто сделать следующее:

  1. Создать переменную @AssignedID
  2. Создать переменную @Version
  3. Получить NextAvailableId от таблицу настроек, а также версию.
  4. Set AssignedID = NextAvailableId
  5. Обновление таблицы параметров, настройка NextAvailableId = AssignedID + 1 WHERE version = @Version
  6. Проверьте обновленное количество строк. Если это 1, нам удалось получить последний идентификатор, увеличить его и сохранить обратно в таблицу, прежде чем другой процесс получит идентификатор.
  7. Если обновленное количество строк было равно нулю, то кто-то схватил число перед нами ... так что попробуйте еще раз, пока у нас не будет обновленной строки.

Это звучит как безопасный и действительный план присвоения «номеров счетов» моему лицу?

Обратите внимание: его нет на самом деле человека или код учетной записи. Это идентификатор поставщика, который должен быть применен к человеку для хранения в отдельной системе. Просто использование Person и Account в качестве (плохого) примера.

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

+3

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

+0

Спасибо @marc_s. Да, это то, что я пытаюсь сделать. Таким образом, обеспечение доступного идентификатора, используя версию строки, кажется мне довольно безопасным. Но, может быть, я что-то упустил? Блокировка? – Craig

+0

[См. Этот другой вопрос SO и ответ Ремуса Русану] (http://stackoverflow.com/questions/5083846/sql-server-2005-using-generated-sequences-instead-of-identity-columns), как это сделать ** безопасно ** –

ответ

2

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

Самый быстрый способ сделать это, чтобы объединить транзакции внутри вашей функции с READ UNCOMMITTED в качестве уровня изоляции и небольшого поля Mutex.Вот псевдо-код:

  1. Начать новую транзакцию с READ неподтвержденными
  2. Проверить это Мьютекс флаг = 0 (нет другой метод работает)
  3. Если флаг = 1, петли
  4. Если флаг = 0, установлен в 1
  5. получить последний ID
  6. Increment, как вы хотите
  7. установите последнюю обратно в таблице ID
  8. Set M UTEX флаг обратно в 0
  9. возвращенного нового идентификатора/Commit транзакция

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

EDIT:

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

CREATE FUNCTION dbo.GetLastId() 
RETURNS INT 
AS 
    BEGIN 
     RETURN SELECT MAX(AccountID) + 1 FROM dbo.tblUsers 
    END 

-- Set the default value to the column 
ALTER TABLE dbo.tblUsers 
ADD AccountID SET DEFAULT (dbo.GetLastId()) 
+1

Вопроситель спросил, безопасен ли он или нет. Параллелизм - плохая сторона его идеи. –

+1

Возможно, что-то о том, что это плохая идея, должно быть в вашем ответе. – dcaswell

+0

Спасибо - «Хотя я не согласен с вашим подходом вручную увеличить последний идентификатор». Единственное, что я могу придумать, это использовать автоматическое увеличение - но по какой-то причине я беспокоюсь, что это тоже не правильный подход. – Craig

Смежные вопросы