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

Использую MSSQL2008R2, Service Broker.

В большом количестве процедур запускается вот такая команда:

send on conversation @lv_dialog_handle message type sb_message_type ....

В последнее время часто стали появляться deadlock, которые обнаруживаются и убиваются автоматически, но от этого легче не становится.
Я запустил профайлер с указанием фиксации дедлок-графа и вот что я обнаружил: лочат друг друга 2 транзакции в которых кроме нескольких селектов и send on conversation в конце ничего нет. Далее посмотрел объект который лочится: через HotBt ID на таблицу partitions, а далее на objects и обнаружил там таблицу sysdesend (которая является таблицей, в которую как я понял и сваливаются все сообщения и которую Service Broker читает - в принципе для меня это не так уж и важно).

Вопрос: как мне избавиться от этих deadlock?

Заранее спасибо.
1 июн 11, 19:37    [10748508]     Ответить | Цитировать Сообщить модератору
 Re: Лочится таблица Service Broker  [new]
Crimean
Member

Откуда:
Сообщений: 13148
добро пожаловать в клуб. опять бесплатный сыр от MS. поскольку таблицы в твоей же базе - работа с ними вносит неразбериху в картину блокировок. избавиться - как от любого дедлока - или вынести за пределы транзакции или согласовать порядок блокировки объектов
1 июн 11, 20:42    [10748705]     Ответить | Цитировать Сообщить модератору
 Re: Лочится таблица Service Broker  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6723
Гость 0601, выложи граф сразу сюда, чтоб не играть в испорченный телефон. Слишком много нюансов.
2 июн 11, 01:53    [10749772]     Ответить | Цитировать Сообщить модератору
 Re: Лочится таблица Service Broker  [new]
Гость 0601
Guest
Crimean, спасибо за совет. Наверное, мы все в этой ловушке :)
Mnior, единственное, что пока могу предоставить это визуальный граф (если скажете, что нужно что-то еще - укажите, пожалуйста, как это что-то еще можно получить) - во вложении
2 июн 11, 09:14    [10750100]     Ответить | Цитировать Сообщить модератору
 Re: Лочится таблица Service Broker  [new]
Гость 0601
Guest
файл не приложился сразу.

К сообщению приложен файл. Размер - 47Kb
2 июн 11, 09:14    [10750105]     Ответить | Цитировать Сообщить модератору
 Re: Лочится таблица Service Broker  [new]
Crimean
Member

Откуда:
Сообщений: 13148
еще нужно имена объектов разрезолвить. а то мы по ИД как-то еще не научились чужие базы читать :)
2 июн 11, 11:51    [10751276]     Ответить | Цитировать Сообщить модератору
 Re: Лочится таблица Service Broker  [new]
Гость 0601
Guest
Crimean, если я правильно Вас понял, то вот:
1) слева овал - это sp1, справа овал - это sp2 (определил из object id в хинте при наведении курсором)
2) в прямоугольниках - то, что лочится. Под HotBt ID в таблице partitions кроется объект sys.sysdesend (читается только с DAC) - lock как раз на ней висит.
2 июн 11, 14:01    [10752536]     Ответить | Цитировать Сообщить модератору
 Re: Лочится таблица Service Broker  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6723
Покажи ещё сами команды (обе!) на которых лочится и вываливается.

send on conversation @lv_dialog_handle message type sb_message_type
sys.sysdesend: Contains a row for each sending endpoint of a Service Broker conversation.

Получается что у вас несколько процессов параллельно обрабатывают один диалог.
2 июн 11, 15:49    [10753792]     Ответить | Цитировать Сообщить модератору
 Re: Лочится таблица Service Broker  [new]
Гость 0601
Guest
Mnior, да Вы правы - несколько параллельных процессов пишут в один диалог. А разве это запрещено?
2 июн 11, 16:06    [10753961]     Ответить | Цитировать Сообщить модератору
 Re: Лочится таблица Service Broker  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6723
Гость 0601
А разве это запрещено?
Вам решать, только на проблемы не жалуйтесь. Никто не запрещает забивать гвозди микроск...
И вообще диалог между двумя субъектами, третьего не дано. А Граф на этом можно сделать любой.

Ладно. Мне интересно что за задача такая, что диалог обрабатывается параллельно, и как вы гарантируете целостность и надёжность?
2 июн 11, 16:48    [10754332]     Ответить | Цитировать Сообщить модератору
 Re: Лочится таблица Service Broker  [new]
Гость 0601
Guest
Mnior, да, конечно, вот коротко о задаче: на сервере крутится программа, которая выполняет различные расчеты в нескольких параллельных потоках. Все расчеты выполняются в ХП, в которых как раз и есть вызов send on conversation. Есть приложение клиентов, которое ожидает от сервера изменений, но чтобы постоянно не тыкаться в сервер запросами по тайм-ауту, клиент просто ожидает wait'ом от сервера события от Service Broker, по названию события сервер обращается к нужному объекту и обновляет данные. То есть по сути реализуется "псевдо"-связь Сервер-Клиент.
3 июн 11, 06:18    [10756576]     Ответить | Цитировать Сообщить модератору
 Re: Лочится таблица Service Broker  [new]
mike909
Member

Откуда:
Сообщений: 662
Гость 0601
Mnior, да, конечно, вот коротко о задаче: на сервере крутится программа, которая выполняет различные расчеты в нескольких параллельных потоках. Все расчеты выполняются в ХП, в которых как раз и есть вызов send on conversation. Есть приложение клиентов, которое ожидает от сервера изменений, но чтобы постоянно не тыкаться в сервер запросами по тайм-ауту, клиент просто ожидает wait'ом от сервера события от Service Broker, по названию события сервер обращается к нужному объекту и обновляет данные. То есть по сути реализуется "псевдо"-связь Сервер-Клиент.


И зачем при этом использовать один диалог в разных потоках ? Объединяйте диалоги в одну группу - и будет Вам счастье ...

Может Вы хотели это: про Service Broker. какие задачи решаются?
3 июн 11, 07:17    [10756628]     Ответить | Цитировать Сообщить модератору
 Re: Лочится таблица Service Broker  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6723
Гость 0601
бла-бла-бла Сервер-Клиент
Стандартная схема RECEIVE TimeOut тут не причём.
Про группы вам написали. Но нам важно другое - виды задач.

Гость 0601
на сервере крутится программа, которая выполняет различные расчеты в нескольких параллельных потоках. Все расчеты выполняются в ХП,
Что за расчёты такие на SQL сервере? Что аж адын запрос клиента настолько ресурсоёмкий что требует N потоков?
3 июн 11, 09:27    [10756895]     Ответить | Цитировать Сообщить модератору
 Re: Лочится таблица Service Broker  [new]
Гость 0601
Guest
mike909, Mnior,
расскажу тогда немного подробнее:
при коннекте пользователя запускается ХП sp_sb_init, где выполняется команда begin dialog, которая возвращает initiator_handle. Далее читается conversation_id таблицы sys.conversation_endpoints по initiator_handle. Дальше создается endpoint для цели (target) командой send on conversation, затем считывается target_handle из sys.conversation_endpoints. Ну и наконец сохраняем в таблицу (например, tb_sb_conversation) ИД пользователя, initiator_handle и target_handle, чтобы потом по имени пользователя понимать, к кому пришло сообщение. Инициализация прошла.

Дальше клиент осуществляет подписку на нужные ему события - здесь все просто: закидывается в таблицу tb_sb_subscribe_event данные по ИД пользователю и имя события. Потом клиент запускает ХП sp_sb_wait_event, где выполняется команда waitfor( receive ... from sb_queue ... where conversation_handle = target_handle из таблицы tb_sb_conversation по ИД текущего пользователя. - это запускается строго в одном потоке на клиенте. Когда что-то приходит, то клиент получает имя события и производит необходимые ему действия (например, вызывается функциональная ХП для чтения обновленных данных).

На сервере, работает программа которая обсчитывает очень много процессов. почему параллельно? да потому что нужно все очень быстро считать и выдавать это клиенту, если что-то изменилось. Программа постоянно запускает ХП и при необходимости вызывается ХП sp_sb_send_event, которая читает список initiator_handle по названию события, которое приходит в качестве параметра в эту ХП, а затем запускает по каждому initiator_handle send on conversation @lv_dialog_handle message type sb_message_type СОБЫТИЕ.

Фуф... вроде все расписал.

mike909, а что значит в группы? и актуально это еще после того, что я описал?
3 июн 11, 14:23    [10759168]     Ответить | Цитировать Сообщить модератору
 Re: Лочится таблица Service Broker  [new]
mike909
Member

Откуда:
Сообщений: 662
Гость 0601
mike909, Mnior,
расскажу тогда немного подробнее:
при коннекте пользователя запускается ХП sp_sb_init, где выполняется команда begin dialog, которая возвращает initiator_handle. Далее читается conversation_id таблицы sys.conversation_endpoints по initiator_handle. Дальше создается endpoint для цели (target) командой send on conversation, затем считывается target_handle из sys.conversation_endpoints. Ну и наконец сохраняем в таблицу (например, tb_sb_conversation) ИД пользователя, initiator_handle и target_handle, чтобы потом по имени пользователя понимать, к кому пришло сообщение. Инициализация прошла.

Как бы это помягче ... -> Зашибись
Т.е. Вы берете работу Srvice Broker_а в свои руки .
Не проще ли повесить сервис, который заполнит Вашу таблицу "tb_sb_conversation" нужными данными ?
В моем примере эту задачу выполняет сервис "широковещательных" сообщений. Алгоритм работы клиента, imho, я достаточно подробно описал.
При Вашем подходе есть подводные камни - Дело в том, что target_handle в sys.conversation_endpoints появляется не сразу после успешного выполнения команы "Send", а только после того как SB доставит сообщение в очередь target_а.
Если Вы предусмотрели эту ситуацию и занимаетесь сканированием sys.conversation_endpoints, то Вы тем самым не только мешаете Service Broker_у работать, но и усиленно пытаетесь получить DeadLock.
Гость 0601
Дальше клиент осуществляет подписку на нужные ему события - здесь все просто: закидывается в таблицу tb_sb_subscribe_event данные по ИД пользователю и имя события.

Ну так используйте первое сообщение после открытия диалога для отправки списка событий, чтоб сервис не только заполнил таблицу "tb_sb_conversation", но еще и таблицу tb_sb_subscribe_event.

Гость 0601
Потом клиент запускает ХП sp_sb_wait_event, где выполняется команда waitfor( receive ... from sb_queue ... where conversation_handle = target_handle из таблицы tb_sb_conversation по ИД текущего пользователя. - это запускается строго в одном потоке на клиенте. Когда что-то приходит, то клиент получает имя события и производит необходимые ему действия (например, вызывается функциональная ХП для чтения обновленных данных).
В моем примере это пункты 3,4,5 клиента.

Гость 0601
На сервере, работает программа которая обсчитывает очень много процессов. почему параллельно? да потому что нужно все очень быстро считать и выдавать это клиенту, если что-то изменилось. Программа постоянно запускает ХП и при необходимости вызывается ХП sp_sb_send_event, которая читает список initiator_handle по названию события, которое приходит в качестве параметра в эту ХП, а затем запускает по каждому initiator_handle send on conversation @lv_dialog_handle message type sb_message_type СОБЫТИЕ.

Пусть Ваша программа тоже не занимается подменой функций Service Broker_а, а после выполнения расчетов просто отправит сообщение тому же сервису, что и клиент, в котором и передаст информацию о событии.
Гость 0601
mike909, а что значит в группы?

Несколько диалогов на одной стороне можно объединить в группу (при создании диалога), что приведет к тому, что только один диалог будет обрабатываться одним Reader_ом, а остальные Reader_ы, читая сообщения по другим диалогам этой группы, не начнут обработку пока не пройдет Commit у первого Reader_а. Такая вот дополнительная синхронизация.

Гость 0601
и актуально это еще после того, что я описал?

Вам решать
4 июн 11, 00:00    [10762234]     Ответить | Цитировать Сообщить модератору
 Re: Лочится таблица Service Broker  [new]
Гость 0601
Guest
mike909, спасибо за развернутый ответ. Почитал Ваш ответ в примере и не совсем понял, что это за сервис "широковещательных" сообщений. Это программа, разработанная Вами или ХП в job или что? Если Вас не затруднит, можете ли Вы подробнее описать это. И если есть возможность, то можно ли взглянуть на Ваш код по инициализации клиента: begin dialog и проч.
Заранее спасибо!
4 июн 11, 08:07    [10762560]     Ответить | Цитировать Сообщить модератору
 Re: Лочится таблица Service Broker  [new]
mike909
Member

Откуда:
Сообщений: 662
Гость 0601
mike909, спасибо за развернутый ответ. Почитал Ваш ответ в примере и не совсем понял, что это за сервис "широковещательных" сообщений. Это программа, разработанная Вами или ХП в job или что? Если Вас не затруднит, можете ли Вы подробнее описать это.

Под сервисом "широковещательных" сообщений я имею ввиду сервис Service Broker_а созданный инструкцией
CREATE SERVICE service_name
[ AUTHORIZATION owner_name ]
ON QUEUE [ schema_name. ]queue_name
[ ( contract_name | [DEFAULT] [ ,...n ] ) ]
[ ; ]
Идея заключается в том, чтобы на этот сервис повесить следующие задачи:
1) Регистрация клиентов и их интересы/подписка в плане "событий".
2) Слежение за тем, что клиенты все еще не потеряли "интерес" к запрошенным событиям. В моем примере это "keepalive".
3) Обеспечить нотификацию клиентов по запрошенным "событиям".
Название сервиса тут не имеет никакого значения. Важно лиш понимание того, что через этот сервис идет общение клиентов и некой исполнительной системой (в Вашем случае это некий сервис расчетов). В примере подразумевался механизм оповещения неопределенного числа клиентов в случае появления некоторого события, например в тригере, после изменения талицы.
Во вторых, что важно, исполнительная система не сама пытается оповестить всех клиентов о неком событии а поручает это дело тому же сервису, т.е. не в тригере пытаемся оповестить, а посылаем событие сервису, чтоб он этим сам занался. Регистрацию клиента и нотификацию его можно обыграть типом сообщения.
Кроме того, если у сервиса будет только один Reader, то блокировок и , тем более DeadLoack_ов, в принципе не будет, так как доступ к таблицам "tb_sb_conversation" и "tb_sb_subscribe_event" осуществляться этим самым "одним reader_ом" в одном потоке. Быстродействия вполне хватит, если на этом задачи этого сервиса и ограничаться. Т.е. Если клиенты будут сами лезть за данными получив уведомление от сервиса.
Гость 0601
И если есть возможность, то можно ли взглянуть на Ваш код по инициализации клиента: begin dialog и проч.
Заранее спасибо!
Мой код уже разросся спецификой и выдрать из него саму "идею" довольно сложно. Да и разбираться в чужом коде не благодарное занатие...
Если, что все еще не понятно, спрашивайте, постараюсь ответить...
6 июн 11, 01:03    [10766641]     Ответить | Цитировать Сообщить модератору
 Re: Лочится таблица Service Broker  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6723
mike909
разбираться в чужом коде не благодарное занатие...
Что не убивает нас - делает нас сильней.
6 июн 11, 01:24    [10766707]     Ответить | Цитировать Сообщить модератору
 Re: Лочится таблица Service Broker  [new]
Верблюд
Member

Откуда: Яженичеловек!!!
Сообщений: 65007
Гость 0601,

Как-то у вас все сложно и мудрено закручено. Не нужно клиенту знание target_handle. Ему достаточно после подключения выполнить begin dialog и получить @initiator_handle, который он вернет. А затем просто тупо выполнить receive from queue where conversation_handle = @initiator_handle и ждать ответа целевого сервиса.
6 июн 11, 19:18    [10772942]     Ответить | Цитировать Сообщить модератору
 Re: Лочится таблица Service Broker  [new]
mike909
Member

Откуда:
Сообщений: 662
Верблюд
Гость 0601,

Как-то у вас все сложно и мудрено закручено. Не нужно клиенту знание target_handle. Ему достаточно после подключения выполнить begin dialog и получить @initiator_handle, который он вернет. А затем просто тупо выполнить receive from queue where conversation_handle = @initiator_handle и ждать ответа целевого сервиса.

Совершенно верно. Клиенту и исполнительной системе (по сути тот же клиент у Гость 0601), этого более чем достаточно.
Да и передавать сервису SB свой handle нет необходимости, т.к. можно связать по sys.conversation_endpoints.[conversation_id] в пределах одной БД (посыпаю голову пеплом).
Но если есть желание позакрывать брошенные клиентами диалоги, скажем во избежании накопления невостребованных сообщений в клиентской очереди, то вполне можно использовать мой алгоритм.

P.S. Вот если бы можно было бы изменять LIFETIME после создания диалога, то обработку брошенных диалогов можно было бы обыграть намного красивей.
7 июн 11, 13:55    [10776613]     Ответить | Цитировать Сообщить модератору
Между сообщениями интервал более 1 года.
 Re: Лочится таблица Service Broker  [new]
Верблюд
Member

Откуда: Яженичеловек!!!
Сообщений: 65007
mike909
Вот если бы можно было бы изменять LIFETIME после создания диалога, то обработку брошенных диалогов можно было бы обыграть намного красивей.


Хммм... пять лет прошло, но отвечу

keepalive на сервисброкере делается просто без всяких дополнительных табличек

1. на стороне клиента для диалога создается DIALOG TIMER, который раз в минуту (например) клиент обрабатывает и посылает серверу сообщение Msg_KeepAlive
2. на стороне сервера для диалога создается DIALOG TIMER, который срабатывает через (допустим) пять минут, и при получении этого сообщения считаем клиента отвалившимся и выполняем END CONVERSATION
3. при получении любого сообщения от клиента кроме ошибки и завершения диалога, переустанавливаем таймер (снова создаем DIALOG TIMER на пять минут)

собственно все.
24 ноя 16, 16:36    [19930732]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить