SQL Server 2008 Service Broker tutorial -- cannot receive the message (exception in transmission_status) - sql-server-2008-r2

I am learning how to use the Service Broker of SQL Server 2008 R2. When following the tutorial Completing a Conversation in a Single Database. Following the Lesson 1, I have successfully created the message types, contract, the queues and services. Following the Lesson 2, I have probably sent the message. However, when trying to receive the message, I get the NULL for the ReceivedRequestMsg instead of the sent content.
When looking at the sys.transmission_queue, the transmission_status for the message says:
An exception occurred while enqueueing a message in the target queue. Error: 15517, State: 1. Cannot execute as the database principal because the principal "dbo" does not exist, this type of principal cannot be impersonated, or you do not have permission.
I have installed SQL Server using the Windows login like Mycomp\Petr. I am using that login also for the lessons.
Can you guess what is the problem? What should I check and or set to make it working?
Edited 2012/07/16: For helping to reproduce the problem, here is what I did. Can you reproduce the error if you follow the next steps?
Firstly, I am using Windows 7 Enterprise SP1, and Microsoft SQL Server 2008 R2, Developer Edition, 64-bit (ver. 10.50.2500.0, Root Directory located at C:\Program Files\Microsoft SQL Server\MSSQL10_50.SQL_PRIKRYL05\MSSQL).
Following the tutorial advice, I have downloaded the AdventureWorks2008R2_Data.mdf sample database, and copied it into C:\Program Files\Microsoft SQL Server\MSSQL10_50.SQL_PRIKRYL05\MSSQL\DATA\AdventureWorks2008R2_Data.mdf
The SQL Server Management Studio had to be launched "As Administrator" to be able to attach the data later. Then I connected the SQL Server.
Right click on Databases, context menu Attach..., button Add..., pointed to AdventureWorks2008R2_Data.mdf + OK. Then selected the AdventureWorks2008R2_Log.ldf from the grid below (reported as Not found) and pressed the Remove... button. After pressing OK, the database was attached and the AdventureWorks2008R2_log.LDF was created automatically.
The following queries were used for looking at "Service Broker enabled/disabled", and for enabling (the Service Broker was enabled successfully for the database):
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
Then, following the tutorial, the queries below were executed to create the message types, the contract, the queues, and the services:
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
So far, so good.
Then the following queries are used to look at the queues (now empty when used):
USE AdventureWorks2008R2;
GO
SELECT * FROM InitiatorQueue1DB WITH (NOLOCK);
SELECT * FROM TargetQueue1DB WITH (NOLOCK);
SELECT * FROM sys.transmission_queue;
GO
The problem manifests when the message is sent:
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
When looking at the queues, the Initiator... and the Target... queues are empty, and the sent message can be found in sys.transmission_queue with the above mentioned error reported via the transmission_status.

alter authorization on database::[<your_SSB_DB>] to [sa];
The EXECUTE AS infrastructure requires dbo to map to a valid login. Service Broker uses the EXECUTE AS infrastructure to deliver the messages. A typical scenario that runs into this problem is a corporate laptop when working from home. You log in to the laptop using cached credentials, and you log in into the SQL using the same Windows cached credentials. You issue a CREATE DATABASE and the dbo gets mapped to your corporate domain account. However, the EXECUTE AS infrastructre cannot use the Windows cached accounts, it requires direct connectivity to the Active Directory. The maddening part is that things work fine the next day at office (your laptop is again in the corp network and can access to AD...). You go home in the evening, continue with Lesson 3... and all of the sudden it doesn't work anymore. Make the whole thing seem flimsy and unreliable. Is just the fact that AD conectivity is needed...
Another scenatio that leads to the same problem is caused by the fact that databases reteint the SID of their creator (the Windows login that issues the CREATE DATABASE) when restored or attached. If you used a local account PC1\Fred when you create the DB and then copy/attach the database to PC2, the account is invalid on PC2 (it is scoped to PC1, of course). Again, not much is affected but EXECUTE AS is, and this causes Service Broker to give the error you see.
And last example is when the DB is created by a user that later leaves the company and the AD account gets deleted. Seems like revenge from his part, but he's innocent. The production DB just stops working, simply because it's his SID that the dbo maps too. Fun...
By simply changing the dbo to sa login you fix this whole EXECUTE AS thing and all the moving parts that depend on it (and SSB is probably the biggest dependency) start working.

You would need to grant receive on your target queue to your login. And it should work!
USE [YourDatabase]
GRANT RECEIVE ON [dbo].[YourTargetQueue]
TO [Mycomp\Petr];
GO
And you also need to grant send for your user, permission on Target Service should be sufficient, but let's enable on both services for the future.
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

Related

How to know if a Firebird 2.0 database is being accessed?

I know that using Firebird 2.5+ I can check if there are users accessing my database using SQL, but unfortunately, Firebird 2.0 doesn't have this feature. Yes, I know it's an old version, but it's a legacy software and I'm not allowed to upgrade this in a short time... :(
I need to know if someone is connected to my 2.0 Firebird database, due to a process I'll run:
Block connections to DB (but ONLY if no one is connected)
Run my process
Allow users to reconnect again
I can start my process only when there are no users connected.
My database is part of a client/server system (no Web).
Any hints?
-at[tach] : this parameter prevents any new connections to the database from being made with the exception of the SYSDBA and the database owner. The shutdown will fail if there are any sessions connected after the timeout period has expired. It makes no difference if those connected sessions belong to the SYSDBA, the database owner or any other user. Any connections remaining will terminate the shutdown with the following details:
https://firebirdsql.org/manual/gfix-dbstartstop.html
There is also Services API to do it so your database access library should expose the shutdown function. Specify a short shutdown, and if it failed - then there were some users. If it succeeded - now you can go on with maintenance, having a warranty client applications will not be able to connect.
Alternatively you can upgrade Firebird 2.0 -> 2.1 which is more close to 2.0 than 2.5 but already have Monitoring Tables implemented.
However this your approach has one weak point - race conditions. Using M.T. you envision your work as following:
Keep querying M.T. (which slows down server work significantly) until there are no other connections.
start maintenance work, that would fail if other connections are active
complete maintenance work
Problem is, that even after at step 1 you gained "no other connection" state, it does not mean that between steps 1 and 2, and especially between steps 2 and 3 now new connections would be made.
Even if you made your checks and ensure #1 condition, when you would go on with maintenance there would be some new user connected back and working now. Not every time of course, but as time goes by it will eventually happen one day.
But there is yet one more good thing in FB 2.1 - database-level triggers.
c:\Program Files\Firebird\Firebird_2_1\doc\sql.extensions\README.db_triggers.txt
You can create a regular "all_current_connections" table, using on connect and on disconnect triggers to keep it up to date.
You perhaps would also have to add some logic to your applications, so they would update that table with your internal application ID, to tell main workflow apps/connections from servicing utilities. However it is also possible that mere CURRENT_USER and CURRENT_CONNECTION pair, which the trigger knows and can store to the table, would be enough for that table, if you can infer kind of application from mere user name.
Then on disconnect trigger might be checking whether all "main workflow" apps disconnected and POST_EVENT to notify servicing utilities. However those utilities would still have to shutdown the database first, anyway.
You can shut down the database using gfix. The gfix tool will try to shutdown the database and if connections still exist after a timeout, the shutdown will fail.
For example, use:
gfix -shut -attach 5 <your-database>
This will:
prevent new connection being created,
wait 5 seconds for the existing connections to end,
if after 5 seconds there are still active connections the shutdown will abort,
otherwise, after 5 seconds the database will be shut down.
After shutdown, only SYSDBA or the database owner can create a connection to the database. This is only a viable option if your application it self doesn't use SYSDBA or the database owner account.
You bring the database back online using:
gfix -online <your-database>
For more information, see also Gfix - Database Housekeeping: Database Startup and Shutdown
Well, not an elegant way, but works...
I try to rename the database file.
If there is someone accessing the database, the rename operation will give me
an exception, saying that the file is in use by some process.
If rename succeeds, new users will not be able to access the database
anymore (the connection string used by my systems is not changed).
I run the exclusive process I have to.
Rename the database file to its original name, allowing new users to
connect again.
I post my solution in the hope that helps someone facing a similar problem.
Our new version of the product will probably a Web application and the database was not choosen yet, but certainly will no be Firebird.
Thanks to all that tried to give me an answer.

The parameter is incorrect (WinMgmt)

I have a BizTalk 2013r2 Standard Edition application server with CU7 installed. The BizTalk databases are hosted on a separate Sql Server 2014 server. This setup has been working fine for many months - until today! A colleague used the BizTalk admin console to make a change to the address BizTalk uses to the reach the SMTP server, by selecting Platform Settings\Adapters\SMTP\\properties.
After making this change, on attempting to refresh the BizTalk Admin Console, the following error is displayed:
From what I've googled, it seems this may be due to some corruption in the SSO database. I have a backup of the SSO database, and a backup of the SSO key along with the password. Before restoring the backup of the SSO database, I wanted to check that I would be able to restore the key, so I ran ssoconfig -restoreSecret from the command line. I was prompted to enter the password. If I intentionally enter the wrong password then it tells me the password is incorrect. However, if I enter the correct password then it displays the message "BAD DATA".
Although the BizTalk admin console is currently unusable, thankfully the BizTalk host instance continue to run and messages are being processed as expected.
Can anyone please suggest why I'm getting the "BAD DATA" message, or perhaps a work-around in order to solve the problem?
I had this problem again and blogged about it at BizTalk WinMgt error solution. As Colin says the hard part is identifying the corrupt handler. It is probably the SMTP send handler but you should check this using WBEMTEST first. I found this link helpful on using WBEMTest. The parameter is incorrect (WinMgt)" error when refreshing the BizTalk Group in BizTalk Administration Console
In my case a quick fix to bring the BizTalk Administration Console back to life was to hack the database. N.B. This probably won't be supported by MS. In my case it was the FTP send handler that screwed up. So I ran
USE [BizTalkMgmtDb]
GO
DECLARE #return_value int
EXEC #return_value = [dbo].[adm_SendHandler2_Delete]
#AdapterName = N'FTP',
#HostName = N'Sending32'
SELECT 'Return Value' = #return_value
GO
At this point the BizTalk Administration console came back to life. In my case it worked because I was creating a new handler but in your case you just edited it. It will take all your SMTP handling out.
I then fixed the corruption using the BizTalk Administration console.
In my case I had to set every FTP receive and send adapter temporarily to a FILE adapter.
I then deleted the FTP adapter and then re-added it. Finally I reset the all the change receive and send location from FILE back to FTP.
This was all very scary on a live system.
Finally I believe that this is bug in BizTalk 2013 R2 because I've seen it happen on 2 systems and now I have heard that the same thing happened to you.
The WinMgt error happens when one of the Adapters setting has gotten itself corrupted. See WinMgt error when refreshing Group Hub
Removing and re-adding the adapter to the host usually fixes it. The trick of course is identifying which Adapter / Host, I would start with the SMTP adapter in your case.

ZSS initial setup failing with invalid connection string

I am trying to get the Zumero for SQL Server working and I cannot get past running the test client. I get the below error
Connection string in web.config is
<settings temp_directory="C:\ProgramData\Zumero\ZSS Server\temp\"
odbc_connection_string="DSN=krishna;User Id=syncadmin;Password=syncadmin;"
license_key="<removed>" />
The description for Event ID 1 from source Zumero cannot be found. Either the component that raises this event is not installed on your local computer or the installation is corrupted. You can install or repair the component on the local computer.
If the event originated on another computer, the display information had to be saved with the event.
The following information was included with the event:
Error -1 (mssql): {"diag":[{"SQL_DIAG_MESSAGE_TEXT":"[Microsoft][ODBC SQL Server Driver][SQL Server]Cannot open database \"ZumeroTest\" requested by the login. The login failed.","SQL_DIAG_NATIVE":4060,"SQL_DIAG_SQLSTATE":"42000"},{"SQL_DIAG_MESSAGE_TEXT":"[Microsoft][ODBC Driver Manager] Driver's SQLSetConnectAttr failed","SQL_DIAG_NATIVE":0,"SQL_DIAG_SQLSTATE":"IM006"},{"SQL_DIAG_MESSAGE_TEXT":"[Microsoft][ODBC SQL Server Driver]Invalid connection string attribute","SQL_DIAG_NATIVE":0,"SQL_DIAG_SQLSTATE":"01S00"}],"SQLRETURN":-1}
..\..\..\src\core\sg\sg_mssql.c:344
..\..\..\src\core\sg\sg_mssql.c:384
..\..\..\src\core\server\zum_db_mssql.c:2896
..\..\..\src\core\server\zum_respond.c:4454
..\..\..\src\servers\iis\main.cpp:1211
The publisher has been disabled and its resource is not avaiable. This usually occurs when the publisher is in the process of being uninstalled or upgraded
Either the SQL Server user doesn't have rights or the database doesn't exist.
You can use a DSN, but for troubleshooting purposes I recommend putting the connection details directly in the connection string for now. Once it's working you can migrate the settings back to a DSN if you like.
Looks like you're using SQL Server authentication. So the odbc_connection_string value should look like this:
Driver={SQL Server Native Client 11.0};Database={database};Server={server.ad.domain.com};UID={sql_server_user};PWD={password};
The database must exist and the user specified must have appropriate read/write access to it.
(If you're setting minimum necessary permissions, you'll also want to make sure the user has VIEW SERVER STATE rights, as described here.)
While unrelated to your invalid connection string problem, the messages about The description for Event ID 1 [...] and The publisher has been disabled [...] indicate that ZSS hasn't been correctly registered with the Windows Event Viewer. Did you install the server by hand (from the .zip file) or using the installer?
You can fix those messages using the following command (which probably requires an admin prompt):
wevtutil im "PATH\TO\events.man" /rf:"PATH\TO\zumero_server.dll" /mf:"PATH\TO\zumero_server.dll"
where PATH\TO is the path where you extracted those files from the .zip. If you used the installer then they should be located at: %PROGRAMFILES%\Zumero\ZSS Server
If you installed manually from the .zip then it's worth noting that the instructions had a subtle typo in that command which would cause it to fail. That typo has been fixed in the past few days, but it may have caught you during your installation and caused this issue.

Creating a linked server from SQL Server 2008r2 to Access 2003

I've written a web app in ASP.NET that stores all of it's data in SQL Server 2008r2 and runs everything via stored procedures. The app is collecting data for a department who wants 2-3 pieces of that data pushed to an old app they use which has a Microsoft Access 2003 backend (.MDB file). My thought was to create a linked server to Access so my app can push everything to SQL server and it can handle it from there (seemed simple enough). Based on info from MSDN (here and here), I was using the following SQL command to create the linked server:
EXEC sys.sp_addlinkedserver #server = N'CMPtesting' ,
#datasrc = N'\\srv.local\SHAREDOCS\MPS\CMPdata.mdb' ,
#srvproduct = N'Access' ,
#provider = N'Microsoft.Jet.OLEDB.4.0'
This completes successfully, and I can see my CMPtesting server listed under Server Objects -> Linked Servers. However, if I try to verify the server using this:
SELECT name FROM [CMPtesting].master.sys.databases
or even just view the tables, I get an error:
OLE DB provider 'Microsoft.Jet.OLEDB.4.0' cannot be used for distributed queries because the provider is configured to run in
single-threaded apartment mode. (Microsoft SQL Server, Error: 7308)
Researching that error led me to "SQL to Access linked server" which suggested installing some different Access drivers and then using #provider = N'Microsoft.ACE.OLEDB.12.0' instead of the Jet driver. Again, this completes successfully, but attempting to view the tables produces a different error:
Cannot create an instance of OLE DB provider "Microsoft.ACE.OLEDB.12.0" for linked server "CMPtesting". (Microsoft
SQL Server, Error: 7302)
I know this is not simply an invalid driver error, because if I just make up a provider name I get this instead:
The OLE DB provider "foobar" has not been registered. (Microsoft SQL Server, Error: 7403)
I'm not sure what else to try because all my searches just turn up more rehashing of how to run sp_addlinkedserver without any additional details or help with these errors.

SQL Studio Management - How to run queries across multiple servers

My 2 server both use SQL Server 2008 R2
I have my local SQL server and also an Amazon machine running an instance of SQL-Server there.
I'm able to connect from my local machine to that Amazon SQL using the standard 10.10.10.10, 1433 connection from my local Management Studio.
What i need to do now is to run a query that says ..tells me what records I have locally that are not on the Amazon server right now.
Something like:
SELECT *
FROM [LOCAL].dbo.Table1
WHERE Field1 NOT IN
(SELECT Field1 FROM [AMAZON].Database1.dbo.Table1)
================================
Question:
I don't know how to write the "AMAZON" location on the Query window itself, since it's running on a different server.
Any help is truly appreciated !!!
You have to configure AMAZON Server as LINKED Server on your local machine. If you name it "AMAZON" - you query will work exactly as you wrote.
In SSMS, \Server Objects\Linked Servers. Right click, 'new linked server'. Name your server, and choose 'SQL server' radio button. Because I was authorized user on both machines with windows credentials, I selected 'Be made using the login's current security context' radio button under the security tab, and did not even have to fool with the local/remote user mappings.
In order to be able to run queries across multiples servers, a link (linked Server) must be established between the 2 Servers. To create a linked server,
Navigate to the Linked Server Sub-folder under the Server Object folders
Right Click on the Linked Server Folder
Click on New Linked Server
Supply the Connection Strings for the Server
Name your Linked Server.
You can now use the full object qualification (LinkedServer.Database.tableOwner.Table) to access the objects.
Good Luck !
You should open your registered server window and create a group for your servers. then you right click the group name and select new query (Or select several servers in that group). if you execute the query it will rung against the servers selected.