Форум: "Базы";
Текущий архив: 2002.09.30;
Скачать: [xml.tar.bz2];
ВнизИскусственная уникальность в . Найти похожие ветки
← →
Александр Спелицин (2002-09-10 18:59) [0]Здравствуйте.
Ситуация с искусственной уникальностью в MSSQL.
Есть таблица: document (doc_id int identity, doc_type int, doc_number int, department_id int, year int, ...).
Номер документа (doc_number) должен быть уникален в пределах заданного отдела (department_id), данного типа (doc_type) и указанного года. Механизм - автоинкремент: максимум + 1.
Т.е. добавление нового документа происходит так:
create procdure CreateFirstTypeDocument @department_id int, @year int, ... какие-то параметры...
as
begin
Declare @doc_nb int
Begin Transaction
-- Точка A
Select @doc_nb = max (doc_number) + 1
From document
Where department_id = @department_id
and year = @year
and doc_type = 1
if @doc_nb Is Null
Select @doc_nb = 1
-- Точка B
Insert document (doc_type, doc_number, department_id, year, ...)
Values (1, @doc_nb, @department_id, @year, ...)
-- Точка C
...
Commit Transaction
end
В таблице одна запись, у которой doc_number = 1. Сервер сильно загружен. Процедуры выполняются медленно.
Теперь из двух сессий одновременно вызывается CreateFirstTypeDocument.
В точке B у для каждой сессии значение @doc_nb будет равно 2. Первая сессия добавляет запись нормально, а вторая своей вставкой нарушает уникальность номеров.
Как обеспечить уникальность?
Заранее спасибо.
← →
wicked (2002-09-10 20:49) [1]если коротко, то код от точки а до точки b просто не нужен...
если тебе нужен id только что вставленной записи, используй системную переменную @@identity...
← →
Александр Спелицин (2002-09-10 20:59) [2]2 wicked:
В том то и дело, что нужен. У каждого подразделения своя нумерация документов. Кроме того, с нового года нумерация вновь начинается с 1.
← →
Виталий Панасенко (2002-09-11 09:53) [3]По-моему (хотя это тут и критикуют :-))) лучше хранить ИД в отдельной таблице. При этом брать оттуда значение и его же увеличивать на 1. Т.к. начата транзакция, все остальные будут ждать ее окончания и только тогда смогут обновить данные.
← →
sniknik (2002-09-11 10:19) [4]Проще хранить начало счетчика года, индетификатор иметь сквозной, а нумерацию делать разницей (чтобы 1 получить в начале года).
← →
Zelius (2002-09-11 10:25) [5]Нужно поставить эксклюзивный Lock на таблицу до окончания транзакции, тогда все документы будут добавляться по очереди и не будут пересекаться. Lock можно поставить либо через подсказки для селекта, либо поставить более высокий уровень изоляции.
← →
doomin (2002-09-11 10:59) [6]Если для каждого типа и департамента должна быть своя нумерация, то тут без отдельной таблицы с номерами не обойтись, все равно нужно сбрасывать вначале года. Там и сбрасывать. И написать процедуру, которой передается тип и отдел, а она возвращает новый номер (читает из таблицы, инкрементирует и перезаписывает в рамках транзакции). На время работы процедуры (это будет недолго, так как табличка маленькая) лочить табличку для всех. Если другая сессия не смогла получить из-за лока номер, то возвращать -1 например и в основной процедуре вставки документа в цикле ждать номера больше 0. Мне кажется так...
Страницы: 1 вся ветка
Форум: "Базы";
Текущий архив: 2002.09.30;
Скачать: [xml.tar.bz2];
Память: 0.46 MB
Время: 0.009 c