Проблемма организации Identity

Vasily
Дата: 25.09.2000 12:51:00
Привет,

Подскажите, как поведет себя сервер в следующем случае:

есть таблица T с полем A int;
по постановки задачи это поле должно вести себя подобно identity c шагом 1.
данное свойство поддерживается с помощью хранимой процедуры типа

declare @A int
SELECT @A = max(A)+1 from T
insert T (A) values (@A)

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

Зарание спасибо.
Василий.
SergSuper
Дата: 25.09.2000 13:18:16
Получиться. Поэтому надо писать:

declare @A int
begin tran
SELECT @A = max(A)+1 from T
insert T (A) values (@A)
commit tran


С приветом Сергей
Vasily
Дата: 25.09.2000 13:48:20
Спасибо, Сергей.

Но тогда возникает следующий вопрос...
Какой уровень изоляции транзакции достаточно поставить?
SergSuper
Дата: 25.09.2000 14:00:58
Ой, я таких умный словей не знаю: уровень изоляции транзакции.
По почте напиши sergsuper@mail.ru или по Аське
Может поймем друг друга
Evgeny
Дата: 25.09.2000 16:55:30
Извиняюсь, что вмешиваюсь.
Уровень изоляции нужен максимальный:
Set Transaction Isolation Level Serializable
Все остальные уровни разрешают добавление данных.
vasily
Дата: 26.09.2000 07:19:27
Да Евгений, я уже докопался до этого, спасибо.
Denis
Дата: 27.09.2000 08:58:47
Я бы порекомендовал во избежания возникновения DeadLock'ов использовать следующую конструкцию:

\ndeclare @A int
begin tran
SELECT @A = max(A)+1 from T WITH (tablockx)
insert T (A) values (@A)
commit tran


при этом уровень изоляции следует выставлять по умолчанию:

\nSET TRANSACTION ISOLATION LEVEL READ COMMITTED

Phil
Дата: 24.10.2000 15:13:12
Я обычно использую отдельную таблицу вида
Create table SIdentity (
[table] varchar(255) NOT NULL PRIMARY,
[ident] int NOT NULL
)

и при определении следующего значения
begin tran
select @i = ident from SIdentity where [table] = 'test'
update SIdentity set [ident] = [ident]+1
end trans

Здесь блокируется только одна строка в очень маленькой таблице, которая скорей всего будет в кэше.

Подобную операцию можно выделить в отдельную процедуру GET_IDENTITY и пользоваться для разных таблиц.
Очень удобно для общего генератора на несколько таблиц.
alexeyvg
Дата: 24.10.2000 16:07:33
Лучше даже без begin tran...

update SIdentity set [ident] = [ident] + 1, @i = [ident] where [tablename] = 'test'
Denis
Дата: 25.10.2000 15:22:13
А еще лучше
update SIdentity set @i = [ident] = [ident] + 1 where [tablename] = 'test'
:)