У нас есть приложение, которое создает очереди и службы в 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]». Есть ли более быстрый способ закрыть и удалить все или некоторые элементы сервисного брокера?
Спасибо!
==Обновление==
Хорошо, мне потребовалось некоторое время, но ответ ниже действительно решил проблему. Я хотел уточнить для всех, у кого может быть проблема.
Мое приложение правильно закрыло все службы, очереди, контракты и сообщения. На закрытие сервисов ушла целая вечность, потому что в приложении была куча открытых разговоров из-за ошибки. Эти разговоры создавались, использовались для отправки сообщения, а затем закрывались с помощью:
END CONVERSATION @conversation 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
Службы сейчас очень быстро отключаются, ошибка и открытые соединения исчезли.