Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Присвоение номера документа.  [new]
Петр
Member

Откуда: Москва
Сообщений: 793
уже несколько дней не могу придумать что-то стоящее, поделитесь опытом.

Задача: поиск максимального номера документа и присвоение текущему max+1 в многопользовательском режиме. (sql2k + ADO)
условия:
избежать дублей
избежать deadlock-ков.

задача вроде простая но как лучше обеспечить вышеуказанные условия.

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

Если накладывать блокировку на всю таблицу по которой идет поиск max номера, то затормозим всех остальных. Есть мысли создавать какойто признак в некой таблице в которую будет записываться маркер на время поиска, но тут встает вопрос, что делать если пользователь потеряет connect с БД....

какие будут мысли?
21 янв 14, 16:50    [15448023]     Ответить | Цитировать Сообщить модератору
 Re: Присвоение номера документа.  [new]
Glory
Member

Откуда:
Сообщений: 104751
Используйте sp_getapplock в процедуре
21 янв 14, 16:56    [15448064]     Ответить | Цитировать Сообщить модератору
 Re: Присвоение номера документа.  [new]
iap
Member

Откуда: Москва
Сообщений: 47142
Петр,

https://www.sql.ru/forum/701408-1/generatory-v-mssql?hl=?????????

В SQL2012 многие посоветуют SEQUENCE
21 янв 14, 16:56    [15448068]     Ответить | Цитировать Сообщить модератору
 Re: Присвоение номера документа.  [new]
Петр
Member

Откуда: Москва
Сообщений: 793
to Glory

что-то не догоняю в sp_getapplock @Resource - должно быть указано имя процедуры поиска макс. номера ?
21 янв 14, 17:50    [15448393]     Ответить | Цитировать Сообщить модератору
 Re: Присвоение номера документа.  [new]
SERG1257
Member

Откуда:
Сообщений: 2877
Если у вас эта генерация проходит достаточно редко, то бишь коллизии не часты, то можно решать задачу "в лоб": навесить уникальный констрейт, отловить ошибку и повторить генерацию. Плюс - ничего переделывать не надо.
Если генерация часта - то бишь количество ошибок неприемлимо велико, то смотрите в сторону identity, SEQUENCE etc
21 янв 14, 18:28    [15448605]     Ответить | Цитировать Сообщить модератору
 Re: Присвоение номера документа.  [new]
Петр
Member

Откуда: Москва
Сообщений: 793
identity тут не причем,
SEQUENCE в 2000-м вообще нет. Проблема не в поиске следующего номера в том чтобы этот номер одновременно не начали искать несколько пользователей сразу, как следствие нашли один и тот же.

Glory предложил то что надо, только не могу понять как правильно применить sp_getapplock

что-то типа того должно быть :?
create  proc get_new_number 
as
declare	@ret	int
exec	@ret	= sp_getapplock	@Resource	= 'get_new_number'
				,@LockMode	= 'Exclusive' 
				,@LockOwner	= 'Session'
waitfor delay '00:00:30'
select 'The End'
go
21 янв 14, 18:56    [15448760]     Ответить | Цитировать Сообщить модератору
 Re: Присвоение номера документа.  [new]
Glory
Member

Откуда:
Сообщений: 104751
Петр
что-то типа того должно быть :?

Да, что то типа такого

ЗЫ
Имя ресурса может быть любым. Это же логическая блокировка
21 янв 14, 19:12    [15448838]     Ответить | Цитировать Сообщить модератору
 Re: Присвоение номера документа.  [new]
Петр
Member

Откуда: Москва
Сообщений: 793
еще раз хочется уяснить в данном случая блокируется только процедура get_new_number ?

alter  proc get_new_number 
as
set	nocount	on
--begin tran
declare	@ret	int

exec	@ret	= sp_getapplock	@Resource	= 'get_new_number'
				,@LockMode	= 'Exclusive' 
				,@LockOwner	= 'Session'
waitfor delay '00:00:30'

exec @ret = sp_releaseapplock @Resource = 'get_new_number', @LockOwner = 'Session'

select 'The End'
--commit tran
set	nocount	off
21 янв 14, 19:31    [15448918]     Ответить | Цитировать Сообщить модератору
 Re: Присвоение номера документа.  [new]
Glory
Member

Откуда:
Сообщений: 104751
Петр
еще раз хочется уяснить в данном случая блокируется только процедура get_new_number ?

Еще раз - это блокировка логического ресурса, а не физического.
Любой другой коннект, который выполнит этот же код
exec @ret = sp_getapplock @Resource = 'get_new_number'
,@LockMode = 'Exclusive'
,@LockOwner = 'Session'

будет ждать ресура по-имени @Resource.
А если другой коннект не выполнит этот sp_getapplock, то он ничего ждать не будет
21 янв 14, 19:35    [15448939]     Ответить | Цитировать Сообщить модератору
 Re: Присвоение номера документа.  [new]
Петр
Member

Откуда: Москва
Сообщений: 793
все наконец то я понял. Glory - как всегда Respect.

всем спасибо. буду экспериментировать.
21 янв 14, 19:50    [15449010]     Ответить | Цитировать Сообщить модератору
 Re: Присвоение номера документа.  [new]
SERG1257
Member

Откуда:
Сообщений: 2877
Петр
Проблема не в поиске следующего номера в том чтобы этот номер одновременно не начали искать несколько пользователей сразу, как следствие нашли один и тот же.
Ну так не ищите max+1, а вставляйте строку в левую таблицу с identity столбцом чтобы получить гарантированно уникальный номер. Вставленную строчку можете тут же удалить. Тогда никто никого ждать не будет.
21 янв 14, 20:11    [15449114]     Ответить | Цитировать Сообщить модератору
 Re: Присвоение номера документа.  [new]
Gorr
Member

Откуда:
Сообщений: 32
Петр
Есть мысли создавать какойто признак в некой таблице в которую будет записываться маркер на время поиска, но тут встает вопрос, что делать если пользователь потеряет connect с БД....

Эта проблема решается довольно просто. Нужно создать глобальную временную таблицу, наличие которой и будет являться признаком поиска. Если в это время потеряется коннект, то эта таблица будет удалена автоматически
21 янв 14, 20:44    [15449220]     Ответить | Цитировать Сообщить модератору
 Re: Присвоение номера документа.  [new]
Петр
Member

Откуда: Москва
Сообщений: 793
с sp_releaseapplock не все так просто оказалось :(. при одновременном запуске get_new_number (несколько процессов в SMS), получаю deadlock.. что не так делаю?
create  proc get_new_number 
as
set	nocount	on
declare	@LockResult	int
--begin tran
-- наложение блокировки на ресурс
--, @LockTimeout = 30000 - фиксированная задержка мс
exec @LockResult = sp_getapplock @Resource	= 'GNN' ,@LockMode = 'Exclusive', @LockOwner	= 'Session' --'Transaction'
if @LockResult <> 0 return -- Процедура занята

waitfor delay '00:00:05'

exec @LockResult = sp_releaseapplock @Resource = 'GNN', @LockOwner = 'Session'

select 'The End'
--commit tran
set	nocount	off
go


to SERG1257 В identity есть конечно рациональное зерно, но оно далеко от идеала. Если документов несколько 10-ков и по каждому документу несколько номенклатур (не сквозная нумерация), то сколько таких таблиц нужно создавать...

to Gorr. да я об этом думал. но тут надо делать какой то цикл задержки который бы ждал пока эта таблица не будет удалена. идея с sp_releaseapplock более красивая... но что-то я не то делаю...
21 янв 14, 21:47    [15449400]     Ответить | Цитировать Сообщить модератору
 Re: Присвоение номера документа.  [new]
Петр
Member

Откуда: Москва
Сообщений: 793
похоже пора завязывать сам затупил. return там не к чему

alter proc get_new_number 
as
set	nocount	on
declare	@LockResult	int
--begin tran
-- наложение блокировки на ресурс
--, @LockTimeout = 30000 - фиксированная задержка мс
exec @LockResult = sp_getapplock @Resource	= 'GNN' ,@LockMode = 'Exclusive', @LockOwner	= 'Session' --'Transaction'

/*if @LockResult <> 0 
 begin
  rollback tran
  return -- Процедура занята
 end
*/
waitfor delay '00:00:05'

exec @LockResult = sp_releaseapplock @Resource = 'GNN', @LockOwner = 'Session'

select 'The End'
--commit tran
set	nocount	off
go
21 янв 14, 21:58    [15449451]     Ответить | Цитировать Сообщить модератору
 Re: Присвоение номера документа.  [new]
leov
Member

Откуда: С-Петербург
Сообщений: 616
Петр,

вообще-то на @LockResult надо бы смотреть прежде чем что-то по сути делать
21 янв 14, 22:04    [15449486]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить