26

SQL Server 2008 R2 の Service Broker の使用方法を学習しています。チュートリアルCompleting a Conversation in a Single Database に従う場合。レッスン 1に従って、メッセージ タイプ、コントラクト、キュー、およびサービスを正常に作成しました。レッスン 2に続いて、おそらくメッセージを送信しました。ただし、メッセージを受信しようとするとReceivedRequestMsg、送信されたコンテンツの代わりに NULL が返されます。

を見るとsys.transmission_queuetransmission_statusメッセージの は次のように述べています。

ターゲット キューにメッセージをエンキューしているときに例外が発生しました。エラー: 15517、状態: 1. データベース プリンシパルとして実行できません。プリンシパル "dbo" が存在しないか、このタイプのプリンシパルを偽装できないか、権限がないためです。

のような Windows ログインを使用して SQL Server をインストールしましたMycomp\Petr。レッスンでもそのログインを使用しています。

何が問題なのか推測できますか? 動作させるには何を確認または設定する必要がありますか?

2012/07/16 編集:問題の再現を支援するために、私が行ったことを次に示します。次の手順を実行すると、エラーを再現できますか?

まず、Windows 7 Enterprise SP1 と Microsoft SQL Server 2008 R2、Developer Edition、64 ビット (ver. 10.50.2500.0、C:\Program Files\Microsoft SQL Server\MSSQL10_50.SQL_PRIKRYL05\MSSQL にあるルート ディレクトリ) を使用しています。 .

  1. チュートリアルのアドバイスに従って、AdventureWorks2008R2_Data.mdf サンプル データベースをダウンロードし、C:\Program Files\Microsoft SQL Server\MSSQL10_50.SQL_PRIKRYL05\MSSQL\DATA\AdventureWorks2008R2_Data.mdf にコピーしました。

  2. 後でデータを添付できるようにするには、SQL Server Management Studio を「管理者として」起動する必要がありました。次に、SQL Server に接続しました。

  3. [データベース] を右クリックし、コンテキスト メニュー [アタッチ...]、[追加...] ボタン、AdventureWorks2008R2_Data.mdf + OK をポイントします。次に、下のグリッドから AdventureWorks2008R2_Log.ldf を選択し (見つかりませんでした)、[削除...] ボタンを押しました。OK を押すと、データベースがアタッチされ、AdventureWorks2008R2_log.LDF が自動的に作成されました。

  4. 次のクエリは、"Service Broker の有効化/無効化" を確認するため、および有効化するために使用されました (Service Broker はデータベースに対して正常に有効化されました)。


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_queuetransmission_status

4

2 に答える 2

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

EXECUTE ASインフラストラクチャはdbo、有効なログインにマップする必要があります。Service Brokerは、EXECUTEASインフラストラクチャを使用してメッセージを配信します。この問題が発生する典型的なシナリオは、自宅で仕事をしているときの企業のラップトップです。キャッシュされたクレデンシャルを使用してラップトップにログインし、同じWindowsのキャッシュされたクレデンシャルを使用してSQLにログインします。を発行するCREATE DATABASEと、dboが企業ドメインアカウントにマッピングされます。ただし、EXECUTEASインフラストラクチャはできませんWindowsのキャッシュアカウントを使用するには、ActiveDirectoryに直接接続する必要があります。厄介な部分は、翌日オフィスで問題なく動作することです(ラップトップは再び企業ネットワークにあり、ADにアクセスできます...)。あなたは夕方に家に帰り、レッスン3を続けます...そして突然それはもう機能しなくなります。全体を薄っぺらで信頼できないように見せます。ADの接続性が必要であるという事実だけです...

同じ問題を引き起こす別のシナリオは、データベースがCREATE DATABASE復元または接続されたときに作成者のSID(を発行するWindowsログイン)を保持するという事実によって引き起こされます。DBを作成し、データベースをPC2にコピー/接続するときにローカルアカウントを使用した場合PC1\Fred、そのアカウントはPC2では無効です(もちろん、スコープはPC1です)。繰り返しますが、あまり影響を受けませんが、EXECUTE ASは影響を受けます。これにより、ServiceBrokerは表示されたエラーを出します。

最後の例は、後で会社を辞めたユーザーがDBを作成し、ADアカウントが削除された場合です。彼の側からの復讐のようですが、彼は無実です。本番DBは、マップするのが彼のSIDであるという理由だけで、機能を停止します。dbo楽しい...

ログインに変更するだけで、dboこのsaEXECUTE AS全体を修正し、それに依存するすべての可動部分(およびSSBがおそらく最大の依存関係)が機能し始めます。

于 2012-07-19T13:12:49.903 に答える
5

ターゲット キューでの受信をログインに許可する必要があります。そして、それはうまくいくはずです!

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
于 2012-07-12T19:24:52.503 に答える