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

Откуда:
Сообщений: 13147
есть простой код

create table #a ( id int )

...

begin tran

declare @I int
select @I = count(*) from MyTable with (xlock) where id in ( select id from #a )

...

commit


внезапно дедлочит на 2 конкурентных ветках. повторить не могу. а граф есть. вопрос - как повторить в лабораторных условиях?
да! на MyTable на Id индекс есть и он кластерный. и дедлок на нем. записей в #a от 2 до 4. не больше и не меньше.
19 фев 16, 18:30    [18842757]     Ответить | Цитировать Сообщить модератору
 Re: deadlock  [new]
Speshuric
Member

Откуда: г. Москва
Сообщений: 129
Crimean,

а можно граф показать? Там точно на КИ, а не, например, на констрейнтах дедлок?
19 фев 16, 18:39    [18842783]     Ответить | Цитировать Сообщить модератору
 Re: deadlock  [new]
ggg-1
Guest
Crimean,

1. Думаю, если Вы приложите граф - людям будет интереснее.
2. Как я понимаю, первый процесс, участвующий в deadlock - это приведенный код.
Вы уверены, что второй процесс, который участвует в deadlock-е - это этот же код?
Просто как-то приведенный пример выглядит немного странновато. Вы явно этот код не из профайлера или deadlock-графа вытягивали.
19 фев 16, 18:41    [18842792]     Ответить | Цитировать Сообщить модератору
 Re: deadlock  [new]
Crimean
Member

Откуда:
Сообщений: 13147
точно. самую малость адаптированная версия:

  <resource-list>
<keylock hobtid="1111" dbid="5" objectname="MyTable" indexname="IMyTable_Id" id="lock4629b41100" mode="X" associatedObjectId="1111">
<owner-list>
<owner id="process2e43498" mode="X" />
</owner-list>
<waiter-list>
<waiter id="process749734dc38" mode="X" requestType="wait" />
</waiter-list>
</keylock>
<keylock hobtid="1111" dbid="5" objectname="MyTable" indexname="IMyTable_Id" id="lock1ca87e500" mode="X" associatedObjectId="1111">
<owner-list>
<owner id="process749734dc38" mode="X" />
</owner-list>
<waiter-list>
<waiter id="process2e43498" mode="X" requestType="wait" />
</waiter-list>
</keylock>
</resource-list>
19 фев 16, 18:42    [18842794]     Ответить | Цитировать Сообщить модератору
 Re: deadlock  [new]
Crimean
Member

Откуда:
Сообщений: 13147
конкурентно работает одна и та же хранимка
там код примитивный, на 100% совпадает с примером
<executionStack> один и тот же
trancount на входе "1", что как бы исключает "потерянную" транзакцию, которая была бы очень кстати - с ней как раз все просто БЫЛО БЫ. но trancount = 1
19 фев 16, 18:44    [18842797]     Ответить | Цитировать Сообщить модератору
 Re: deadlock  [new]
Speshuric
Member

Откуда: г. Москва
Сообщений: 129
Crimean
точно. самую малость адаптированная версия:

  <resource-list>
<keylock hobtid="1111" dbid="5" objectname="MyTable" indexname="IMyTable_Id" id="lock4629b41100" mode="X" associatedObjectId="1111">
<owner-list>
<owner id="process2e43498" mode="X" />
</owner-list>
<waiter-list>
<waiter id="process749734dc38" mode="X" requestType="wait" />
</waiter-list>
</keylock>
<keylock hobtid="1111" dbid="5" objectname="MyTable" indexname="IMyTable_Id" id="lock1ca87e500" mode="X" associatedObjectId="1111">
<owner-list>
<owner id="process749734dc38" mode="X" />
</owner-list>
<waiter-list>
<waiter id="process2e43498" mode="X" requestType="wait" />
</waiter-list>
</keylock>
</resource-list>


objectname="MyTable" - так она с решёткой или без?
19 фев 16, 18:49    [18842810]     Ответить | Цитировать Сообщить модератору
 Re: deadlock  [new]
Speshuric
Member

Откуда: г. Москва
Сообщений: 129
сорри, ступил
19 фев 16, 18:50    [18842815]     Ответить | Цитировать Сообщить модератору
 Re: deadlock  [new]
Crimean
Member

Откуда:
Сообщений: 13147
попытка репро работает на 2 сценариях уже с часик. естественно, безрезультатно.
19 фев 16, 18:56    [18842831]     Ответить | Цитировать Сообщить модератору
 Re: deadlock  [new]
Speshuric
Member

Откуда: г. Москва
Сообщений: 129
Crimean,

А план запроса есть?
19 фев 16, 19:32    [18842933]     Ответить | Цитировать Сообщить модератору
 Re: deadlock  [new]
Crimean
Member

Откуда:
Сообщений: 13147
Speshuric,

нет, плана нет. и получить проблематично. но у меня сходные идеи и я собираюсь добавить во времянку ПК и написать там JOIN а не IN, чтобы оптимизатору "неповадно" было :)
19 фев 16, 19:34    [18842946]     Ответить | Цитировать Сообщить модератору
 Re: deadlock  [new]
Speshuric
Member

Откуда: г. Москва
Сообщений: 129
Crimean,

Ну вообще я почти уверен, что причина в том, что по каким-то причинам SQL в разном порядке подбирает, то, что в #a валяется. А чтобы понять почему - нужно план смотреть. Я попробовал вставлять значения в #a в разном порядке (1, 10000 и наоборот 10000, 1), но там у меня в плане сортировка стоит. Вот и интересно какой план в оригинале. Хотя бы не в сам момент дедлока, а "по жизни" или из кеша
19 фев 16, 19:39    [18842968]     Ответить | Цитировать Сообщить модератору
 Re: deadlock  [new]
Speshuric
Member

Откуда: г. Москва
Сообщений: 129
ну и эта... select @@version :)
19 фев 16, 19:41    [18842981]     Ответить | Цитировать Сообщить модератору
 Re: deadlock  [new]
invm
Member

Откуда: Москва
Сообщений: 9845
При данном раскладе дедлок возможен если #a соединяется с MyTable по NL и в разных сеансах пересекающиеся наборы id в #a в разном порядке.
Достаточно легко воспроизводится.
19 фев 16, 19:45    [18842994]     Ответить | Цитировать Сообщить модератору
 Re: deadlock  [new]
Speshuric
Member

Откуда: г. Москва
Сообщений: 129
invm,

Может и просто, но вот я попробовал воспроизвести, у меня да, нестед лупы в соединении в плане, но только вот #a перед этим сортируется (и, очевидно, дедлок не воспроизводится). Версия 10.50.6000.34
19 фев 16, 19:48    [18843003]     Ответить | Цитировать Сообщить модератору
 Re: deadlock  [new]
invm
Member

Откуда: Москва
Сообщений: 9845
Speshuric
но только вот #a перед этим сортируется
А вы с count(*) воспроизводили? С count distinct sort после NL.
19 фев 16, 19:56    [18843025]     Ответить | Цитировать Сообщить модератору
 Re: deadlock  [new]
msLex
Member

Откуда:
Сообщений: 9311
у меня воспроизводится после 3 - 20 секунд работы.

создаем таблицу в 1кк записей (не пинайте за кросджойн/spt_values и прочее
create table dbo.MyTable (id int not null primary key )

;with cte as (
	select distinct number
	from master.dbo.spt_values
	where number >= 1 and  number <= 1000
	
)
, N as (
	select 
		number = (t1.number - 1)  * 1000 + t2.number
	from cte t1
	cross join cte t2
)
insert dbo.MyTable(id)
select N.number
from n



в двух окнах запускаем скрипт с бесконечным суммированием


set nocount on
if object_id('tempdb..#a') is not null
	drop table #a
create table #a ( id int )
go

-- вставляем 1000 детерменированных, но размазанных по всей исходной таблицы записей
insert #a(
	id
)
select id
from dbo.MyTable with(nolock)
where 
	id % 1000 = 0
go


-- сортируем таблицу поиска в случайном порядке
alter table #a add sort_key uniqueidentifier null 
go
update #a set sort_key = NEWID()
go
create clustered index i on #a (sort_key)
go

while 1=1 
begin
	begin tran

	declare @I int
	select @I = count(*) 
	-- форсируем index seek и блокировку на уровне строки
	from dbo.MyTable with (xlock, rowlock, forceseek) 
	where id in ( 
		select id from #a 
	) 
	-- форсируем параллелизм
	option(QUERYTRACEON 8649)


	commit
end 
19 фев 16, 20:03    [18843050]     Ответить | Цитировать Сообщить модератору
 Re: deadlock  [new]
invm
Member

Откуда: Москва
Сообщений: 9845
Еще вот так можно воспроизвести:
+ Поготовка
use tempdb;
go

create view dbo.vNow as select getdate() as [now];
go

create function dbo.fnDelay
(
 @ms int
)
returns int
as
begin
 declare @dt datetime;

 select @dt = [now] from dbo.vNow;

 while exists(select 1 from dbo.vNow where datediff(ms, @dt, [now]) < @ms)
  set @dt = @dt;

 return 1;
end;
go

create table dbo.t(id int primary key);

insert into dbo.t
select top (1000)
 row_number() over (order by rand())
from
 master.dbo.spt_values a cross join
 master.dbo.spt_values b;
go

Далее в первой сессии запускаем
use tempdb;
go

declare @t table (id int);
insert into @t values (1), (2);

set statistics xml on;

select
 count(*)
from
 dbo.t with (xlock, rowlock, forceseek)
where
 dbo.fnDelay(case when id = 1 then 10000 else 0 end) = 1 and
 id in (select id from @t);

set statistics xml off;
Во второй запускаем
use tempdb;
go

declare @t table (id int);
insert into @t values (2), (1);

set statistics xml on;

select
 count(*)
from
 dbo.t with (xlock, rowlock, foceseek)
where
 dbo.fnDelay(case when id = 2 then 10000 else 0 end) = 1 and
 id in (select id from @t);

set statistics xml off;
19 фев 16, 20:20    [18843129]     Ответить | Цитировать Сообщить модератору
 Re: deadlock  [new]
Crimean
Member

Откуда:
Сообщений: 13147
спасибо. в обоих случаях индексирование поля ИД решает проблему.
19 фев 16, 20:28    [18843159]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить