У нас есть приложение, которое создает очереди и службы в SQL Server, используя Service Broker для обработки связи с БД. Приложение использует эти службы и правильно отправляет / получает сообщения, но теперь я хочу проверить фазу инициализации этого приложения (оно создает посредника, а также хранимые процедуры, которые работают за кулисами). По сути, мне нужно отбрасывать элементы брокера с некоторой частотой, и сейчас это действительно очень медленно.
Я могу изменить способ, которым приложение создает элементы посредника, если это помогает - но этот вопрос больше связан с выключением всего.
Код, который я использую для выключения брокера:
receive * from [dbo].[notify_initiator_queue]
alter queue [dbo].[notify_initiator_queue] with status = OFF
drop service [//DBNotifyService-Initiator]
drop queue [dbo].[notify_initiator_queue]
drop message types, contacts, etc...
Это некоторое время зависает при 'отбрасывании службы [// XF / DBNotifyService-Initiator]'. Есть ли более быстрый способ закрыть и удалить все или некоторые элементы компонента Service Broker?
Спасибо!
== Обновление ==
Хорошо, это заняло у меня некоторое время, но ответ ниже решил проблему. Я хотел бы уточнить для кого-то еще, что может быть проблема.
Мое приложение правильно отключило все службы, очереди, контракты и сообщения. Закрытие сервисов заняло целую вечность, потому что в приложении было множество открытых разговоров об ошибке. Эти разговоры создавались, использовались для отправки сообщения, а затем закрывались:
END CONVERSATION @conversation with cleanup
Бит 'with cleanup' закрывает только локальный конец диалога (возможно, он позволяет серверу очистить любые разговоры, которые могли быть допущены с ошибкой на другом конце). Он не закрывает другой конец службы отправки, поэтому разговоры оставались открытыми. Обычные разговоры должны быть закончены:
END CONVERSATION @conversation
Это исправило ошибку приложения. Тем не менее, у меня было несколько миллионов прерванных разговоров в БД. Я мог бы бросить БД, как нормальный человек, или я мог бы попытаться выяснить, как их закрыть. Чтобы закрыть их всех по одному требуется:
declare @conversation uniqueidentifier
while exists (select top 1 conversation_handle from sys.transmission_queue )
begin
set @conversation = (select top 1 conversation_handle from sys.transmission_queue )
end conversation @conversation with cleanup
end
Это занимает несколько мс на соединение (очень медленно для миллионов). Если я хочу закрыть их все очень быстро, используйте ответ ниже и выполните измененную команду:
ALTER DATABASE [" + target.getTargetDbName() + "] SET NEW_BROKER WITH ROLLBACK IMMEDIATE;
Немедленный откат приводит к разрыву всех соединений, не позволяя им гарантировать фиксацию. В документации говорится: «Все незавершенные транзакции будут отменены, а любые другие подключения к образцу базы данных AdventureWorks2008R2 будут немедленно отключены». http://msdn.microsoft.com/en-us/library/bb522682.aspx
Сервисы теперь очень быстро отключаются, ошибка и открытые соединения исчезли.