Database Owner Conundrum

Posted by Johnm on Simple Talk See other posts from Simple Talk or by Johnm
Published on Sat, 05 Jun 2010 19:30:14 GMT Indexed on 2010/06/05 19:33 UTC
Read the original article Hit count: 331

Filed under:

Have you ever restored a database from a production environment on Server A into a development environment on Server B and had some items, such as Service Broker, mysteriously cease functioning? You might want to consider reviewing the database owner property of the database.

The Scenario
Recently, I was developing some messaging functionality that utilized the Service Broker feature of SQL Server in a development environment. Within the instance of the development environment resided two databases: One was a restored version of a production database that we will call "RestoreDB". The second database was a brand new database that has yet to exist in the production environment that we will call "DevDB". The goal is to setup a communication path between RestoreDB and DevDB that will later be implemented into the production database.

After implementing all of the Service Broker objects that are required to communicate within a database as well as between two databases on the same instance I found myself a bit confounded. My testing was showing that the communication was successful when it was occurring internally within DevDB; but the communication between RestoreDB and DevDB did not appear to be working.

Profiler to the rescue
After carefully reviewing my code for any misspellings, missing commas or any other minor items that might be a syntactical cause of failure, I decided to launch Profiler to aid in the troubleshooting. After simulating the cross database messaging, I noticed the following error appearing in Profiler:

An exception occurred while enqueueing a message in the target queue. Error: 33009, State: 2. The database owner SID recorded in the master database differs from the database owner SID recorded in database '[Database Name Here]'. You should correct this situation by resetting the owner of database '[Database Name Here]' using the ALTER AUTHORIZATION statement.

Now, this error message is a helpful one. Not only does it identify the issue in plain language, it also provides a potential solution. An execution of the following query that utilizes the catalog view sys.transmission_queue revealed the same error message for each communication attempt:

SELECT
    *
FROM   
    sys.transmission_queue;

Seeing the situation as a learning opportunity I dove a bit deeper.

Reviewing the database properties 
The owner of a specific database can be easily viewed by right-clicking the database in SQL Server Management Studio and selecting the "properties" option. The owner is listed on the "General" page of the properties screen. In my scenario, the database in the production server was created by Frank the DBA; therefore his server login appeared as the owner: "ServerName\Frank". While this is interesting information, it certainly doesn't tell me much in regard to the SID (security identifier) and its existence, or lack thereof, in the master database as the error suggested.

I pulled together the following query to gather more interesting information:

SELECT
    a.name
    , a.owner_sid
    , b.sid
    , b.name
    , b.type_desc
FROM   
    master.sys.databases a
    LEFT OUTER JOIN master.sys.server_principals b
        ON a.owner_sid = b.sid
WHERE
    a.name not in ('master','tempdb','model','msdb');

This query also helped identify how many other user databases in the instance were experiencing the same issue. In this scenario, I saw that there were no matching SIDs in server_principals to the owner SID for my database. What login should be used as the database owner instead of Frank's? The system stored procedure sp_helplogins will provide a list of the valid logins that can be used. Here is an example of its use, revealing all available logins:

EXEC sp_helplogins; 

Fixing a hole
The error message stated that the recommended solution was to execute the ALTER AUTHORIZATION statement. The full statement for this scenario would appear as follows:

ALTER AUTHORIZATION ON DATABASE:: [Database Name Here] TO [Login Name];

Another option is to execute the following statement using the sp_changedbowner system stored procedure; but please keep in mind that this stored procedure has been deprecated and will likely disappear in future versions of SQL Server:

EXEC dbo.sp_changedbowner @loginname = [Login Name];

.And They Lived Happily Ever After
Upon changing the database owner to an existing login and simulating the inner and cross database messaging the errors have ceased. More importantly, all messages sent through this feature now successfully complete their journey. I have added the ownership change to my restoration script for the development environment.

© Simple Talk or respective owner