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

Откуда: Москва
Сообщений: 2
Подскажите пожалуйста, может ли возникнуть дедлок в такой процедуре:

SET TRANSACTION ISOLATION LEVEL REPEATABLE READ
BEGIN TRAN
IF
(	SELECT U_CurrentKey
	FROM [@GTTABLEKEYS]
	WITH (XLOCK, TABLOCKX)
	WHERE Name = '{0}'
) IS NULL
BEGIN
	declare @newKey    as Int
	declare @newKeyTbl as Numeric(19,6)
	set @newKey = (select isnull(max(cast(Code as Int)),-1) + 1 from [@GTTABLEKEYS])
	if (select count(*) from [{0}]) = 0
		set @newKeyTbl = 0
	else
		set @newKeyTbl = (select isnull(max(cast(Code as Int)),-1) from [{0}])
	insert into [@GTTABLEKEYS] (Code, Name, U_CurrentKey)
	values(@newKey, '{0}', @newKeyTbl)
END

update [@GTTABLEKEYS]
set U_CurrentKey = U_CurrentKey + 1
where Name = '{0}'

select U_CurrentKey
from [@GTTABLEKEYS]
where Name = '{0}'

COMMIT TRAN

где {0} заменяется на имя таблицы...


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

Хотя когда я тестирую код и вызываю эту процедуру в каждом из 90 одновременных отдельных потоков, то все работает нормально и никаких дедлоков нет.
18 июн 13, 16:56    [14449286]     Ответить | Цитировать Сообщить модератору
 Re: deadlock возможен в такой процедуре?  [new]
Glory
Member

Откуда:
Сообщений: 104760
Positiff88
Задача в том, чтобы при одновременном вызове этой процедуры многоми процессами, все ее вызовы были бы последовательными и не возникало бы дедлоков. Судя по всему при загрузке сервера дедлоки при выполнении все же возникают иногда.

Дедлок может возникнуть даже в одном единственном коннекте.

Positiff88
Судя по всему при загрузке сервера дедлоки при выполнении все же возникают иногда.

Тогда вы можете легко получить граф дедлока и узнать причины его возникновения.
18 июн 13, 17:04    [14449332]     Ответить | Цитировать Сообщить модератору
 Re: deadlock возможен в такой процедуре?  [new]
Positiff88
Member

Откуда: Москва
Сообщений: 2
Glory
Дедлок может возникнуть даже в одном единственном коннекте.

Как может возникнуть дедлок при одном единственном обращении к данным? Он что сам себя залочит?

Glory
Тогда вы можете легко получить граф дедлока и узнать причины его возникновения.

Боюсь, что сделать это довольно проблематично ибо дедлоки возникали очень редко и в этот момент у клиентов не был настроен deadlock trace.

Может быть по коду процедуры удастся оценить ее дедлокоустойчивость?)
Как видно, весь код выполняется в транзакции и для таблицы явно указан уровень блокировки.
Предполагалось, что этого будет достаточно, чтобы данные в таблице [@GTTABLEKEYS] изменялись последовательно.
Может кто-то видит какое-то "слабое" место, где может возникнуть дедлок?
18 июн 13, 17:32    [14449527]     Ответить | Цитировать Сообщить модератору
 Re: deadlock возможен в такой процедуре?  [new]
Glory
Member

Откуда:
Сообщений: 104760
Positiff88
Glory
Дедлок может возникнуть даже в одном единственном коннекте.

Как может возникнуть дедлок при одном единственном обращении к данным? Он что сам себя залочит?

Именно.
Например, таблица и некластерный индекс по ней есть два независимых объекта/ресурса. А дедлок и есть конфликт при доступе к двум ресурсам. Количество коннектов при этом роли не играет.
18 июн 13, 17:47    [14449622]     Ответить | Цитировать Сообщить модератору
 Re: deadlock возможен в такой процедуре?  [new]
aleks2
Guest
а чо, проще то низзя?
;
merge [@GTTABLEKEYS] g WITH (XLOCK, TABLOCKX)
  using ( select Name = '{0}', newKeyTbl = (select isnull(max(cast(Code as Int)),-1) from [{0}]) ) s
  on (g.Name = s.Name)
  when not matched then
    insert(Code, Name, U_CurrentKey)
      values( s.newKeyTbl+1, s.Name, case when exists(select * from [{0}]) then s.newKeyTbl+1 else 1 end )
  when matched then
    update [@GTTABLEKEYS]
    set U_CurrentKey = U_CurrentKey + 1
  output inserted.U_CurrentKey
18 июн 13, 19:27    [14450148]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить