SQL Server 2008 R2のService Brokerの使用方法を学習しています。チュートリアル 単一データベースでの会話の完了 に従う場合。 レッスン1 に続いて、メッセージタイプ、コントラクト、キュー、およびサービスを正常に作成しました。 レッスン2 に続いて、おそらくメッセージを送信しました。ただし、メッセージを受信しようとすると、送信されたコンテンツではなくReceivedRequestMsg
のNULLが表示されます。
sys.transmission_queue
を見ると、メッセージのtransmission_status
は次のように述べています。
ターゲットキューにメッセージをエンキューするときに例外が発生しました。エラー:15517、状態:1.プリンシパル「dbo」が存在しない、このタイプのプリンシパルが偽装できない、または権限がないため、データベースプリンシパルとして実行できません。
Mycomp\Petr
のようなWindowsログインを使用してSQL Serverをインストールしました。レッスンにもそのログインを使用しています。
何が問題だと思いますか?機能させるには何を確認または設定する必要がありますか?
2012年7月16日編集:問題の再現を助けるために、ここで私がやったことをします。次の手順に従うと、エラーを再現できますか?
まず、Windows 7 Enterprise SP1、Microsoft SQL Server 2008 R2、Developer Edition、64ビットを使用しています(バージョン10.50.2500.0、ルートディレクトリは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を選択し([見つかりません]と報告されます)、[削除...]ボタンを押しました。 [OK]を押すと、データベースが接続され、AdventureWorks2008R2_log.LDFが自動的に作成されました。
次のクエリは、 "Service Broker enabled/disabled"の確認と有効化(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_queue
にあり、上記のエラーはtransmission_status
を介して報告されます。
alter authorization on database::[<your_SSB_DB>] to [sa];
EXECUTE ASインフラストラクチャでは、有効なログインにマップするためにdbo
が必要です。 Service Brokerは、EXECUTE ASインフラストラクチャを使用してメッセージを配信します。この問題が発生する典型的なシナリオは、自宅で仕事をしているときの企業のラップトップです。キャッシュされた資格情報を使用してラップトップにログインし、同じWindowsキャッシュされた資格情報を使用してSQLにログインします。 CREATE DATABASE
を発行すると、dbo
が企業ドメインアカウントにマッピングされます。ただし、EXECUTE AS infrastructre cannotはWindowsキャッシュアカウントを使用するため、Active Directoryへの直接接続が必要です。厄介なのは、翌日オフィスで問題なく機能することです(ラップトップは再び社内ネットワークにあり、ADにアクセスできます...)。夕方に家に帰ってレッスン3に進むと、突然突然機能しなくなります。全体が薄っぺらで信頼できないものに見えるようにします。 ADの接続性が必要であるという事実だけです...
同じ問題につながるもう1つの状況は、データベースが復元またはアタッチされたときに、作成者のSID(CREATE DATABASE
を発行するWindowsログイン)を繰り返すという事実が原因です。ローカルアカウントPC1\Fred
を使用してDBを作成し、データベースをPC2にコピー/アタッチした場合、アカウントはPC2では無効です(スコープはPC1です)。繰り返しますが、それほど影響はありませんが、EXECUTE ASは影響を受けます。これにより、Service Brokerが表示するエラーを発生させます。
最後の例は、後で退職するユーザーによってDBが作成され、ADアカウントが削除される場合です。彼からの復讐のようですが、彼は無実です。 dbo
もマッピングするhis SIDであるという理由だけで、本番DBは機能しなくなります。楽しい...
dbo
ログインをsa
ログインに変更するだけで、このEXECUTE AS全体を修正し、それに依存するすべての可動部分(およびSSBがおそらく最大の依存関係)が機能し始めます。
ターゲットキューでの受信をログインに許可する必要があります。そしてそれはうまくいくはずです!
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