присвоение серийного номера клиенту из пула серийных номеров - PullRequest
0 голосов
/ 22 апреля 2009

У меня есть таблица серверов с лицензионными ключами / серийными номерами. Структура таблицы выглядит примерно так:

[
RecordId int,
LicenceKey string,
Status int (available, locked, used, expired etc.)
AssignedTo int (customerId)
....
]

Через мое приложение ASP.NET, когда пользователь решает купить лицензию, нажимая кнопку подтверждения, мне нужно зарезервировать лицензионный ключ для пользователя. Мой подход, как, Выберите top 1 licenceKey из KeysTable, где Status = доступно Обновить статус KeysTable Set = заблокирован затем верните ключ обратно в приложение.

Меня беспокоит, если два потока asp.net обращаются к одной и той же записи и возвращают один и тот же ключ лицензии. Как вы думаете, что является лучшей практикой выполнения таких заданий? Есть ли общеизвестный подход или закономерность такого рода проблем? Где использовать операторы lock (), если они мне нужны?

Я использую Sql Server 2005, хранимые процедуры для доступа к данным, DataLayer, BusinessLayer и Asp.Net GUI.

Спасибо

Ответы [ 4 ]

4 голосов
/ 22 апреля 2009

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

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

Примерно так:

UPDATE TOP (1) KeysTable
SET Status = 'locked'
OUTPUT INSERTED.LicenseKey
-- if you want more than one column...
-- OUTPUT INSERTED.RecordID, INSERTED.LicenseKey
-- if you want all columns...
-- OUTPUT INSERTED.*
WHERE Status = 'available'
1 голос
/ 22 апреля 2009

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

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
GO
BEGIN TRANSACTION

--Execute select
--Execute update

COMMIT TRANSACTION

Однако, почему у вас есть таблица с каждым возможным лицензионным ключом? Почему бы не иметь алгоритм генерации ключей, а затем создавать новый ключ, когда пользователь покупает его?

0 голосов
/ 22 апреля 2009

Вы также можете попробовать использовать блокировки (в SQL) в дополнение к транзакциям, чтобы убедиться, что только один поток имеет доступ одновременно.

Я считаю, что здесь может помочь блокировка приложения.

0 голосов
/ 22 апреля 2009

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

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

РЕДАКТИРОВАТЬ: Блокировка в бизнес-логике, вероятно, будет работать, если вы можете гарантировать, что только один процесс изменит базу данных, но гораздо лучше сделать это на уровне базы данных, предпочтительно в одном хранимом процессе. Чтобы сделать это правильно, вы должны установить уровень транзакции и использовать транзакции в базе данных, как @Adam Robinson предложил в своем ответе.

...