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

Откуда: Киев
Сообщений: 66
Всем доброго дня!

До недавнего времени был уверен, что для дедлока нужны хотя бы два процесса. Ниже привожу скрипт, который в моем случае гарантированно дедлочит сам себя.

Может кто-то объяснить на пальцах из-за чего это происходит?

Microsoft SQL Server 2008 R2 (RTM) - 10.50.1600.1 (Intel X86) Apr 2 2010 15:53:02 Copyright (c) Microsoft Corporation Developer Edition on Windows NT 5.1 <X86> (Build 2600: Service Pack 3) (Hypervisor)

Msg 1205, Level 13, State 55, Procedure TUO_Proc, Line 3
Transaction (Process ID 56) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction.

К сообщению приложен файл (Гарантированный Deadlock.sql - 659bytes) cкачать
2 июл 12, 13:26    [12803642]     Ответить | Цитировать Сообщить модератору
 Re: Deadlock процессом самого себя  [new]
Гавриленко Сергей Алексеевич
Member

Откуда:
Сообщений: 37254
А создавать тип данных и использовать его в одной и той же транзакции - это так надо, или просто эффект продемонстрировать?
2 июл 12, 13:30    [12803681]     Ответить | Цитировать Сообщить модератору
 Re: Deadlock процессом самого себя  [new]
Валентин К.
Member

Откуда: Киев
Сообщений: 66
Конечно же, именно так я и обошел эту проблему. Но остался академический интерес, может быть кому-то понятно почему это происходит именно в случае общей транзакции
2 июл 12, 13:35    [12803736]     Ответить | Цитировать Сообщить модератору
 Re: Deadlock процессом самого себя  [new]
Гавриленко Сергей Алексеевич
Member

Откуда:
Сообщений: 37254
Граф надо смотреть. Обламывается на компиляции, потому что запись в системных таблицах есть, но заблокирована.
2 июл 12, 13:36    [12803753]     Ответить | Цитировать Сообщить модератору
 Re: Deadlock процессом самого себя  [new]
Crimean
Member

Откуда:
Сообщений: 13147
крайне странный пример.
2 июл 12, 14:51    [12804442]     Ответить | Цитировать Сообщить модератору
 Re: Deadlock процессом самого себя  [new]
Валентин К.
Member

Откуда: Киев
Сообщений: 66
Crimean,
А у Вас эта проблема воспроизводится?
Исходно это был скрипт обновления версии продакшн базы, поэтому была попытка все изменения сделать в общей транзакции. В упрощенном виде скрипт и правда выглядит странно
2 июл 12, 15:56    [12804940]     Ответить | Цитировать Сообщить модератору
 Re: Deadlock процессом самого себя  [new]
Crimean
Member

Откуда:
Сообщений: 13147
Валентин К.,

воспроизводится, ага:

Server: Msg 1205, Level 13, State 55, Procedure TUO_Proc, Line 3
Transaction (Process ID 51) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction.

но не пойму - для чего делать тип + хранимку и после выполнять эту же хранимку в этой же транзакции?
если хранимку выполнить после транзакции - дедлок уйдет
2 июл 12, 16:17    [12805173]     Ответить | Цитировать Сообщить модератору
 Re: Deadlock процессом самого себя  [new]
Валентин К.
Member

Откуда: Киев
Сообщений: 66
Crimean,

То, что проблема уйдет если вынести из транзакции - это понятно. Так я в итоге и сделал.

Для чего все исходно было в одной транзакции могу вкратце объяснить (хотя наверное это не так важно с точки зрения понимания Deadlock'а). Этот скрипт - это исходно скрипт обновления версии базы, которое, в идеале, было бы неплохо сделать в одной транзакции. В процессе обновления создаются технологические объекты, (которые живут только во время обновления базы и облегчают обновление). Процедура и табличный тип - некоторые из таких объектов.

Вообще, как обойти проблему понятно (я ее уже обошел), не понятна причина дедлока (ну в смысле, на мой взгляд у SQL странное поведение в этом случае)
2 июл 12, 16:56    [12805564]     Ответить | Цитировать Сообщить модератору
 Re: Deadlock процессом самого себя  [new]
Glory
Member

Откуда:
Сообщений: 104751
Валентин К.
не понятна причина дедлока (ну в смысле, на мой взгляд у SQL странное поведение в этом случае)

Причину показывает граф дедлока.
2 июл 12, 16:57    [12805574]     Ответить | Цитировать Сообщить модератору
 Re: Deadlock процессом самого себя  [new]
Crimean
Member

Откуда:
Сообщений: 13147
Валентин К.,

я подозреваю это проблемы от новомодных табличных параметров
2 июл 12, 17:39    [12805825]     Ответить | Цитировать Сообщить модератору
 Re: Deadlock процессом самого себя  [new]
Crimean
Member

Откуда:
Сообщений: 13147
а вот и граф

<deadlock-list>
 <deadlock victim="process41cd708">
  <process-list>
   <process id="process41cd708" taskpriority="0" logused="0" waitresource="METADATA: database_id = 2 USER_TYPE(user_type_id = 257)" waittime="2386" ownerId="156658543" transactionname="@ObjectList" lasttranstarted="2012-07-02T16:57:47.263" XDES="0x14982f950" lockMode="Sch-S" schedulerid="4" kpid="7876" status="suspended" spid="54" sbid="0" ecid="0" priority="0" trancount="1" lastbatchstarted="2012-07-02T16:57:47.260" lastbatchcompleted="2012-07-02T16:57:47.253" clientapp="SQL Query Analyzer" hostname="TURBO" hostpid="4868" loginname="SC\Crimean" isolationlevel="read committed (2)" xactid="156658539" currentdb="2" lockTimeout="4294967295" clientoption1="536938528" clientoption2="119808">
    <executionStack>
     <frame procname="unknown" line="3" sqlhandle="0x03000200cfa6491c2f8b170182a000000100000000000000">
unknown     </frame>
     <frame procname="adhoc" line="1" stmtend="30" sqlhandle="0x010002000c33b81bb01220ed000000000000000000000000">
EXEC #TUO_Proc     </frame>
    </executionStack>
    <inputbuf>
EXEC #TUO_Proc
COMMIT TRAN
    </inputbuf>
   </process>
  </process-list>
  <resource-list>
   <metadatalock subresource="USER_TYPE" classid="user_type_id = 257" dbid="2" id="locked39d300" mode="Sch-M">
    <owner-list>
     <owner id="process41cd708" mode="Sch-M"/>
    </owner-list>
    <waiter-list>
     <waiter id="process41cd708" mode="Sch-S" requestType="wait"/>
    </waiter-list>
   </metadatalock>
  </resource-list>
 </deadlock>
</deadlock-list>
2 июл 12, 18:10    [12806060]     Ответить | Цитировать Сообщить модератору
 Re: Deadlock процессом самого себя  [new]
Crimean
Member

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

К сообщению приложен файл. Размер - 23Kb
2 июл 12, 18:12    [12806067]     Ответить | Цитировать Сообщить модератору
 Re: Deadlock процессом самого себя  [new]
Валентин К.
Member

Откуда: Киев
Сообщений: 66
Crimean,

спасибо за ответ!

Подозреваю, что так оно и есть. По крайней мере использование табличного типа для задания типа параметра процедуры также приводит к дедлоку. Интересно, что процесс process41cd708 уже удерживает Sch-M блокировку, но при этом не может наложить Sch-S блокировку. Sch-M препятствовала бы наложению блокировки Sch-S, если бы эти блокировки накладывали разные процессы. Но это один процесс. В этом для меня главная странность.
2 июл 12, 18:28    [12806134]     Ответить | Цитировать Сообщить модератору
 Re: Deadlock процессом самого себя  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6724
Валентин К.
не понятна причина дедлока (ну в смысле, на мой взгляд у SQL странное поведение в этом случае)
Правильно думаете товарищ.
Crimean
я подозреваю это проблемы от новомодных табличных параметров
А я подозреваю что в последних костыльных обходах проблемы. IMXO
Вот только какой не могу нарыть.

На 2008 я заметил безобразие с расстановкой локов схемы. Sch-M будь он неладен.
Вот только к дедлоку не приводило ... пока.
Хотя здесь случай донельзя идиотский.

Валентин К.
По крайней мере использование табличного типа
А что, его использование вне процедуры тоже валится?
2 июл 12, 21:05    [12806531]     Ответить | Цитировать Сообщить модератору
 Re: Deadlock процессом самого себя  [new]
step_ks
Member

Откуда:
Сообщений: 936
Mnior
А что, его использование вне процедуры тоже валится?

Похоже на то.
BEGIN TRAN
GO
CREATE TYPE dbo.ObjectName AS  TABLE (Name sysname NULL);
GO
DECLARE @ObjectList dbo.ObjectName
GO
if @@trancount>0 ROLLBACK TRAN
GO


Msg 1205, Level 13, State 55, Line 1
Transaction (Process ID 52) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction.
2 июл 12, 22:46    [12806766]     Ответить | Цитировать Сообщить модератору
 Re: Deadlock процессом самого себя  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6724
Ок.
Тогда банальности. Есть вероятности параллельности некоторых процессов.
К примеру процесса описалова (создание в схеме) и процесса создания переменной по вышеописанному образу и подобию (в tempdb).
Тем более что переменные работают вне транзакции.

Интересно, а с остальными (не табличного типа) пользовательскими типами также?
2 июл 12, 23:03    [12806794]     Ответить | Цитировать Сообщить модератору
 Re: Deadlock процессом самого себя  [new]
Валентин К.
Member

Откуда: Киев
Сообщений: 66
Mnior,

Заменил табличный тип простым пользовательским типом, CREATE TYPE [dbo].[MyInt] FROM [int] NULL

Дедлок не возникает.

Похоже, проблема как-то связана с компиляцией пакетов, в которых используются табличные переменные (что требует Sch-S на табличный тип). При этом процесс компиляции выполняется в отдельном (внутреннем) по отношению к вызывающему процессу, так что его блокировки (накладываемые процессом компиляции) не воспринимаются как родные для пользовательского процесса, что приводит к конфликту с Sch-M пользовательского процесса. К сожалению, я не особо разбираюсь в том, как происходит процесс компиляции. Понимаю, что это больше похоже на мешанину мыслей, чем на объяснение
3 июл 12, 11:59    [12808825]     Ответить | Цитировать Сообщить модератору
 Re: Deadlock процессом самого себя  [new]
tunknown
Member

Откуда:
Сообщений: 775
Валентин К.
Похоже, проблема как-то связана с компиляцией пакетов, в которых используются табличные переменные (что требует Sch-S на табличный тип). При этом процесс компиляции выполняется в отдельном (внутреннем) по отношению к вызывающему процессу,


CREATE TYPE dbo.qwerty_table1 AS  TABLE (qwerty_column int)
BEGIN TRAN
CREATE TYPE dbo.qwerty_table AS  TABLE (qwerty_column int)
exec('DECLARE @qwerty_var1 dbo.qwerty_table1
DECLARE @qwerty_var dbo.qwerty_table')


Такой скрипт показывает проблему в более изолированном виде. В профилере видно, что перед самим Lock:Deadlock Chain(SPID=6) вмешивается другой процесс (SPID=13..26/TASK MANAGER). Возможно, он имеет к компиляции какое-то отношение. Блокировки у него не совсем ясные.
3 июл 12, 15:51    [12810775]     Ответить | Цитировать Сообщить модератору
 Re: Deadlock процессом самого себя  [new]
aleonov
Member

Откуда:
Сообщений: 96
вот еще в копилку странности с типами:


Из документации:

автор
Note:
When alias data types are dropped, they can still be referenced by table
variables later in the batch in which they were dropped.



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

Example 1
CREATE TYPE dbo.ObjectName AS  TABLE (Name sysname NULL);
GO
BEGIN TRAN
drop type dbo.ObjectName
DECLARE @ObjectList dbo.ObjectName
GO
if @@trancount>0 ROLLBACK TRAN
GO


Example 2
drop type dbo.ObjectName
go
BEGIN TRAN
CREATE TYPE dbo.ObjectName AS  TABLE (Name sysname NULL);
DECLARE @ObjectList dbo.ObjectName
if @@trancount>0 ROLLBACK TRAN
GO
3 июл 12, 16:50    [12811268]     Ответить | Цитировать Сообщить модератору
 Re: Deadlock процессом самого себя  [new]
Валентин К.
Member

Откуда: Киев
Сообщений: 66
Выполнил скрипт
BEGIN TRAN
CREATE TYPE dbo.qwerty_table AS  TABLE (qwerty_column int)
exec('DECLARE @qwerty_var dbo.qwerty_table')
--ROLLBACK TRAN	

Пока дедлок не был перехвачен системой в другом окне выполнил скрипт
SELECT * 
FROM 
sys.dm_tran_locks tl Left outer join 
sys.dm_tran_active_transactions tat On tat.transaction_id = tl.request_owner_id 


Из него видно что владелец блокировки Sch-S, которая в этот момент находится в состоянии ожидания, имеет специфический request_owner_id (2505805), отличающийся от request_owner_id остальной транзакции (2505801). То же касается request_owner_lockspace_id. Инфа из BOL, касающаяся request_owner_lockspace_id: This value represents the lockspace ID of the requestor. The lockspace ID determines whether two requestors are compatible with each other and can be granted locks in modes that would otherwise conflict with one another.
Может быть я ошибаюсь, но выглядит это так, как будто работа с табличной переменной ведется в контексте транзакции, независимой от пользовательской (не вложенной в нее). Наверное поэтому откат пользовательской транзакции откатывает данные в табличной переменной.

К сообщению приложен файл. Размер - 50Kb
4 июл 12, 18:24    [12818126]     Ответить | Цитировать Сообщить модератору
 Re: Deadlock процессом самого себя  [new]
Валентин К.
Member

Откуда: Киев
Сообщений: 66
Наверное поэтому откат пользовательской транзакции не откатывает данные в табличной переменной.
4 июл 12, 18:25    [12818144]     Ответить | Цитировать Сообщить модератору
 Re: Deadlock процессом самого себя  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6724
Валентин К.
Наверное поэтому откат пользовательской транзакции не откатывает данные в табличной переменной.
Не понимаю вашу робость в высказывании.
Естественно что работа с переменными не завязана на контекстной транзакции.

НО, вы показали что она работает в другой транцакции, а это более точно. Потому что могло быть к примеру вообще без понятия транзакция.
Понятно, нужно привязаться к схеме. Но какого хрена это делает система хранения данных в темповых таблах, а не та же самая контекстная транзакция (запуск процедуры).
Тот "поток", который отвечает за данные переменных (на tempdb), на схемы должно быть на$рать, он получил структуру, а далее что с ней далее творится - фиолетово. Не может же порождающийся поток кукнуться раньше (хотя на самом деле это не важно).

Кстати, вопрос на засыпку - кто-то меж-базово вызывал процедуры с табличными параметрами?!

Видно что дали долбанутому индусу сию реализацию, а в логику всей системы он и не вникал. Или тупо схалтурил.

В багтрекер надо так и записать - "перепутан идентификатор потока лочащий схему".
Валентин К., завести можете? Плюсану.

При этом дописать: "M$, перед тем как послать на by design, опиши какого хрена оно так".
5 июл 12, 00:44    [12819597]     Ответить | Цитировать Сообщить модератору
 Re: Deadlock процессом самого себя  [new]
Валентин К.
Member

Откуда: Киев
Сообщений: 66
У меня есть подозрение, что это все не ошибка, а by design. Deadlock - всего лишь нежелательное следствие реализации табличных переменных, т.к., с одной стороны, табличная переменная должна вести себя как обычная переменная (а значит не участвовать в транзакции), а с другой, в некотором роде она все же является таблицей (а значит должна суметь откатить как одну транзакцию команду вроде Insert into @TableVariable (PrimaryKeyField) From Values (1), (2), (3), (1))). Для реализации этого поведения, в итоге, они вынуждены для каждой DML-команды с табличной переменной использовать транзакцию (я даже где-то читал, что для возможности отката вынуждены что-то писать в Transaction log), но при этом они также вынуждены сделать ее независимой от охватывающей пользовательской транзакции. В итоге возможность Deadlock'а - плата за такое разделение.
В общем, присоединяюсь к высказанному Crimean мнению, что "это проблемы от новомодных табличных параметров".
5 июл 12, 11:59    [12821056]     Ответить | Цитировать Сообщить модератору
 Re: Deadlock процессом самого себя  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6724
Валентин К., если вы меня не поняли так и пишите.
Вроде как ясно написал.
Структура переменной принадлежит текущему процессу, данные нет.
Да, для целостности tempdb (где размещаются переменные, временные таблицы и версионность строк) транзакция нужна. Но зачем ей блокировать структуру?
Незачем! Информация о структуре таблицы считывает тукущим процессом (2505801) передаётся в другой процесс (2505805).

А в реале получается фигово:
2505801: мне нужна таблица типа [Schema].[TableType]
System: Порождение "процесса" 2505805
2505805: Привет, зачем вызывали?
2505801: мне нужна таблица типа [Schema].[TableType]
2505805: Ok, а в какой она базе?
2505801: В [MyBase]
2505805: Ищу структуру [MyBase].[Schema].[TableType]
2505805: Блокирую для чтения [MyBase].[Schema].[TableType]
2505805: Копирую структуру [MyBase].[Schema].[TableType]
2505805: Создаю таблицу в tempdb
2505805: 2505801, лови ссылку
2505801: Наконец

А должно быть так:
2505801: Ищу структуру [MyBase].[Schema].[TableType]
2505801: Блокирую для чтения [MyBase].[Schema].[TableType]
2505801: Считываю структуру [MyBase].[Schema].[TableType]
2505801: мне нужна таблица такой сруктуры Table(Bla-Bla)
System: Порождение "процесса" 2505805, передача параметра
2505805: Создаю таблицу структуры Table(Bla-Bla) в tempdb
2505805: 2505801, лови ссылку
2505801: Оперативно
Утрированно, но хоть дошло?
Валентин К.
для каждой DML-команды
Спорно, табличные переменные создатся до запуска процедуры/батча (см трейсы и объекты tempdb) (после компиляции но до запуска).
5 июл 12, 18:56    [12824366]     Ответить | Цитировать Сообщить модератору
 Re: Deadlock процессом самого себя  [new]
Валентин К.
Member

Откуда: Киев
Сообщений: 66
Mnior,

Спасибо за подробные разъяснения. Явно моей квалификации недостаточно, чтобы пытаться вникать в тему на таком уровне.
В багтреккере регистрировать проблему не буду, т.к. в моем случае ее легко обойти и для меня ее решение от майкрософт не принципиально. Да и, как я уже говорил, поведение системы мне кажется обоснованным. Но если вы понимаете, почему должно быть по-другому - регистрируйте, я не против :)

В любом случае, спасибо всем, кто проявил интерес к теме :)
6 июл 12, 13:41    [12828498]     Ответить | Цитировать Сообщить модератору
Топик располагается на нескольких страницах: [1] 2   вперед  Ctrl      все
Все форумы / Microsoft SQL Server Ответить