Подтвердить что ты не робот

SQL Server 2008 Service Broker - не может получать сообщение (исключение в передаче_стату)

Я изучаю, как использовать Service Broker SQL Server 2008 R2. При выполнении учебника Завершение беседы в одной базе данных. Следуя Lesson 1, я успешно создал типы сообщений, контракт, очереди и службы. Следуя Lesson 2, я, вероятно, отправил сообщение. Однако при попытке получить сообщение я получаю NULL для ReceivedRequestMsg вместо отправленного содержимого.

Когда вы смотрите sys.transmission_queue, transmission_status для сообщения говорит:

Исключение произошло при размещении сообщения в целевой очереди. Ошибка: 15517, Состояние: 1. Невозможно выполнить в качестве принципала базы данных, так как основной "dbo" не существует, этот тип принципала не может быть выдан или у вас нет разрешения.

Я установил SQL Server с помощью входа в Windows, например Mycomp\Petr. Я также использую этот логин для уроков.

Можете ли вы догадаться, в чем проблема? Что я должен проверить и/или настроить, чтобы он работал?

Отредактировано 2012/07/16:. Чтобы помочь воспроизвести проблему, вот что я сделал. Можете ли вы воспроизвести ошибку, если будете следовать следующим шагам?

Во-первых, я использую Windows 7 Enterprise SP1 и Microsoft SQL Server 2008 R2, Developer Edition, 64-разрядный (версия 10.50.2500.0, Root Directory, расположенная в C:\Program Files\Microsoft SQL Server\MSSQL10_50.SQL_PRIKRYL05\MSSQL).

  • Следуя советам, я загрузил базу данных примеров AdventureWorks2008R2_Data.mdf и скопировал ее в C:\Program Files\Microsoft SQL Server\MSSQL10_50.SQL_PRIKRYL05\MSSQL\DATA\AdventureWorks2008R2_Data.mdf

  • Чтобы добавить данные позже, необходимо запустить SQL Server Management Studio "Как администратор". Затем я подключил SQL Server.

  • Щелкните правой кнопкой мыши на Базах данных, в контекстном меню Прикрепить..., кнопка Добавить..., указана на AdventureWorks2008R2_Data.mdf + OK. Затем выбрали AdventureWorks2008R2_Log.ldf из нижеприведенной сетки (сообщено как "Не найдено" ) и нажали кнопку "Удалить...". После нажатия кнопки "ОК" база данных была подключена, и AdventureWorks2008R2_log.LDF был создан автоматически.

  • Следующие запросы были использованы для просмотра "Включен/отключен служебный брокер" и для включения (Брокер службы был успешно включен для базы данных):


USE master;
GO

SELECT name, is_broker_enabled FROM sys.databases;
GO

ALTER DATABASE AdventureWorks2008R2
      SET ENABLE_BROKER
      WITH ROLLBACK IMMEDIATE;
GO

SELECT name, is_broker_enabled FROM sys.databases;
GO
  • Затем, после учебника, выполнялись следующие запросы для создания типов сообщений, контракта, очередей и служб:

USE AdventureWorks2008R2;
GO

CREATE MESSAGE TYPE
       [//AWDB/1DBSample/RequestMessage]
       VALIDATION = WELL_FORMED_XML;
CREATE MESSAGE TYPE
       [//AWDB/1DBSample/ReplyMessage]
       VALIDATION = WELL_FORMED_XML;
GO

CREATE CONTRACT [//AWDB/1DBSample/SampleContract]
      ([//AWDB/1DBSample/RequestMessage]
       SENT BY INITIATOR,
       [//AWDB/1DBSample/ReplyMessage]
       SENT BY TARGET
      );
GO

CREATE QUEUE TargetQueue1DB;

CREATE SERVICE
       [//AWDB/1DBSample/TargetService]
       ON QUEUE TargetQueue1DB
       ([//AWDB/1DBSample/SampleContract]);
GO

CREATE QUEUE InitiatorQueue1DB;

CREATE SERVICE
       [//AWDB/1DBSample/InitiatorService]
       ON QUEUE InitiatorQueue1DB;
GO

До сих пор так хорошо.

  • Затем для просмотра очередей (теперь пустых при их использовании) используются следующие запросы:

USE AdventureWorks2008R2;
GO

SELECT * FROM InitiatorQueue1DB WITH (NOLOCK);
SELECT * FROM TargetQueue1DB WITH (NOLOCK);
SELECT * FROM sys.transmission_queue;
GO
  • Проблема проявляется при отправке сообщения:

BEGIN TRANSACTION;

BEGIN DIALOG @InitDlgHandle
     FROM SERVICE
      [//AWDB/1DBSample/InitiatorService]
     TO SERVICE
      N'//AWDB/1DBSample/TargetService'
     ON CONTRACT
      [//AWDB/1DBSample/SampleContract]
     WITH
         ENCRYPTION = OFF;

SELECT @RequestMsg =
       N'<RequestMsg>Message for Target service.</RequestMsg>';

SEND ON CONVERSATION @InitDlgHandle
     MESSAGE TYPE 
     [//AWDB/1DBSample/RequestMessage]
     (@RequestMsg);

SELECT @RequestMsg AS SentRequestMsg;

COMMIT TRANSACTION;
GO  

При просмотре очередей очереди Initiator... и Target... пусты, и отправленное сообщение можно найти в sys.transmission_queue с вышеупомянутой ошибкой, сообщенной через transmission_status.

4b9b3361

Ответ 1

alter authorization on database::[<your_SSB_DB>] to [sa];

Для инфраструктуры EXECUTE AS требуется dbo сопоставить действительный логин. Сервисный брокер использует инфраструктуру EXECUTE AS для доставки сообщений. Типичным сценарием, который сталкивается с этой проблемой, является корпоративный ноутбук при работе из дома. Вы регистрируетесь на ноутбуке, используя кэшированные учетные данные, и вы входите в SQL, используя те же кэшированные учетные данные Windows. Вы выдаете CREATE DATABASE, а dbo сопоставляется с корпоративной учетной записью домена. Однако инфраструктура EXECUTE AS не может использовать кэшированные учетные записи Windows, она требует прямой связи с Active Directory. Сумасшедшая часть заключается в том, что на следующий день в офисе все работает нормально (ваш ноутбук снова находится в корпоративной сети и может получить доступ к AD...). Вы возвращаетесь домой вечером, продолжайте с урока 3... и все это внезапно не работает. Сделать все это кажется хлипким и ненадежным. Является ли тот факт, что AD-совместимость необходима...

Другой сценарий, который приводит к одной и той же проблеме, вызван тем, что при восстановлении или присоединении базы данных повторно идентифицируют SID своего создателя (учетная запись Windows, которая выдает CREATE DATABASE). Если вы использовали локальную учетную запись PC1\Fred при создании БД, а затем скопировали/прикрепили базу данных к ПК2, учетная запись недействительна на ПК2 (конечно, она относится к ПК1). Опять же, не так много, но EXECUTE AS is, и это приводит к тому, что Service Broker выдает ошибку, которую вы видите.

И последний пример - когда БД создается пользователем, который позже покидает компанию, и учетная запись AD удаляется. Кажется, месть с его стороны, но он невиновен. Производственный БД просто перестает работать, просто потому, что его SID, который отображает dbo. Развлечения...

Просто изменив логин dbo на sa, вы исправите всю эту вещь EXECUTE AS, и все движущиеся части, которые зависят от нее (и SSB, вероятно, самая большая зависимость) начинают работать.

Ответ 2

Вам нужно будет предоставить получать в своей целевой очереди свой логин. И это должно сработать!

USE [YourDatabase]
GRANT RECEIVE ON [dbo].[YourTargetQueue]
TO [Mycomp\Petr];
GO

И вам также необходимо предоставить отправку для своего пользователя, разрешение на целевую службу должно быть достаточным, но разрешить включение обеих служб на будущее.

USE AdventureWorks2008R2 ;
GO

GRANT SEND ON SERVICE::[//AWDB/1DBSample/InitiatorService]
TO [Mycomp\Petr] ;
GO

GRANT SEND ON SERVICE::[//AWDB/1DBSample/TargetService]
TO [Mycomp\Petr] ;
GO