There's another change to the SQL Server database engine in SQL Server 2008 R2. This concerns poison-message handling behavior in Service Broker applications.

Service broker's messaging is always transactional. A RECEIVE SQL statement is transactional and can be combined with other database operations as part of a transaction. For example, you can code a RECEIVE for a Service Broker queue combined with an INSERT of a database row, based on the information in the message. If the transaction fails (say the row's primary key already exists), the message that was RECEIVEd will be put back on the queue. But then, the next RECEIVE could read the same message again; if the message is never able to be processed correctly, and the RECEIVE-INSERT-ERROR-ROLLBACK statement can loop on this particular message. This is known as a poison message.

It is suggested that you write your own poison message handling strategy, a few strategies are listed here. If you do not write your own strategy, Service Broker's default strategy (which happens after five consecutive transaction rollbacks) is to disable the queue. You can receive a QUEUE_DISABLED event if you write a service broker service that handles the BROKER_QUEUE_DISABLED event notification.

Some folks have complained that this is a fairly drastic step (and limits the poison message-handling strategies you can write), but poison message loops do have the capability to waste SQL Server resources. So...

In SQL Server 2008 R2, both the CREATE QUEUE and ALTER QUEUE DDL statements allow the (new) specification POISON_MESSAGE_HANDLING(STATUS = OFF/ON). According to the description "This allows for a custom poison message handing system to be defined by the application." This does not relieve you from writing your own strategy, it just means that you can turn off disabling the queue for a 5-rollback poison message.

I'm not usually one to post product announcements, but I had to point out that the Service Broker External Activator shipped with the latest (Oct 2008) version of SQL Server 2008 feature pack. It's available here.

Doing a quick "visual diff" with the August 2008 feature pack, I also notice some new PowerShell extensions, SQLXML 4.0 SP1, and a number of items for Reporting Services (including, of course, Report Builder 2.0), Analysis Services (including ADOMD.NET and some interesting datamining report viewer controls) and the SAP BI connector.

Lots of new items.

More about Service Broker priority in SQL Server 2008.

The books online states, when setting a initiator/target priority as local service name/remote service name that the priority affects:

1. Sends from the initiator queue
2. Receives from the initiator queue
3. Getting the next conversation group from the initiator queue.

And specifies the mirror image priority for target/initiator as local service name/remote service name affects:

1. Receives from the target queue
2. Sends from the target service
3. Getting the next conversation group from the target queue

So, in my previous example, where

The initiator/target as local service name/remote service name is priority 7
The target/initiator as local service name/remote service name is priority 6

Let's send a message from the initiator that "sticks" in sys.transmission_queue. Suppose that either the network is slow or we don't have the appropriate setup. But the message is floundering in the transmission queue. Already SENT, waiting to be delivered.

"select * from sys.transmission_queue;" shows the message BEING SENT (and transmitted) at priority 7. And, when the message is finally DELIVERED, the priority in the receiveq "select * from receiveq" is priority 6.

Normally, you'd likely make both priorities in the initiator/target pair the same to avoid confusion, but you can make them different for greater granularity. And it DOES help to illustrate where and when priority is used.

Conversation priority is a new feature with SQL Server 2008. In a previous blog post, I talked about how to simply set one up. But you'd usually not want to set up a priority for all messages. So, lets set up a simple service and then define a "Premier Customer" priority. Before trying this you need to make sure the database is set to honor broker priority.

ALTER DATABASE pubs SET HONOR_BROKER_PRIORITY ON;

Suppose I had a simple (one database) service pair. A service called "sender" (note lower case) using senderq is the initiator and a service called "receiver" using receiverq is the target. They use the [default] contract. So we can set up a "Premier Customer" by contract.

CREATE CONTRACT premier ([DEFAULT] SENT BY ANY);
GO

Now, let's ensure that the target can also use the premier contract in addition to the DEFAULT contract.

ALTER SERVICE receiver ON QUEUE receiveq (ADD CONTRACT premier);

We need to set up the priority.

CREATE BROKER PRIORITY PremierCustomer
    FOR CONVERSATION
    SET (CONTRACT_NAME = premier,
         LOCAL_SERVICE_NAME = sender,
         REMOTE_SERVICE_NAME = 'receiver',
         PRIORITY_LEVEL = 7);
GO

The interesting thing is, this priority ONLY covers messages sent and received (and get conversation group) by the sender/senderq, IT DOESN'T cover the receives in the receiver/receiveq queue. So we'll set up a mirror image priority, and make the priority level still higher than the default (5) but gratuitously different than the other priority

CREATE BROKER PRIORITY PremierCustomer2
    FOR CONVERSATION
    SET (CONTRACT_NAME = premier,
         LOCAL_SERVICE_NAME = receiver,   -- local service is receiver
         REMOTE_SERVICE_NAME = 'sender', -- remote service is sender
         PRIORITY_LEVEL = 6);                   -- note level 6, not 7
GO

Now, begin a conversation using sender and receiver and the premier contract and send a message. Note that when you issue "SELECT * FROM sys.conversation_endpoints;" the sender (initiator's) endpoint is priority 7, the receiver's endpoint is priority 6. And, looking at the message in the receiveq its set to priority 6.

If you'd send a return message from the receiver (target) back to the sender (initiator), the return message in the senderq would be priority 7.

So when setting up priorities, if you want all messages on both sides to be affected, don't forget to set up a priority for EACH side. Here's the entire demo.

BrokerPriorityByContractDemo.zip (1.57 KB)

SQL Server 2008 adds the concept of priority for conversations. It's setup using special DDL statements, priority cannot be specified on the CREATE DIALOG CONVERSATION or SEND/RECEIVE DML statements. The DDL statements are CREATE/ALTER/DROP BROKER PRIORITY.

To specify a priority, you associate a BROKER PRIORITY object with combinations of the qualifiers LOCAL_SERIVCE_NAME/REMOTE_SERVICE_NAME/CONTRACT and the priority is associated with all messages and conversation endpoints that match that combination. The wildcard 'ALL' (or leaving the qualifier out entirely) is permitted for any or all of the qualifiers, and matching precidence is specifying in BOL under the CREATE BROKER PRIORITY syntax. The set of defined priorities is stored in sys.conversation_priorities metadata view.

In addition to this setup, the database has to be set to use priorities, with the "ALTER DATABASE...SET HONOR_BROKER_PRIORITY ON" DDL statement. The default behavior is not to honor priorities.

Once you define BROKER PRIORITY(s) and set the database to honor them, priority (default is 5) will be set on:
 sys.conversation_endpoints
 each message in the queue 
 sys.transmission_queue messages

Service Broker priorities are a much asked-for feature and its good to see it implemented. Because this is a new feature in CTP5, there are still some rough edges that need fixing. You can't set honor_broker_priority on CREATE or ATTACH database. And using the SMO scripter (Script As/CREATE on the database in Object Explorer) doesn't set honor_broker_priority either.

There are some really nice examples of the syntax and the concept in BOL. I've enclosed a really simple starter script that changes the default priority and illustrates the metadata. Enjoy.

broker_priority.sql (2.29 KB)

Had to write about another thing that "caught my ear" at TechEd during a chalktalk by Rick Negrin about Service Broker usage patterns.

Service Broker supports "internal activation", that is, associate a stored procedure that gets invoked when a queue has messages to process as well as "external activiation". When using external activation, an event notification occurs when a queue has messages to process, and this notification is picked up by an external application; the external application processes the queue messages, out-of-process to SQL Server.

There is an SSMS template (see template explorer) for an internal activator procedure and an engine sample implementation of a class library to support SQLCLR activator procs. In addition, Remus Rusanu has written some excellent blog entries on activation program message processing patterns.

There is a sample implementation of an external activator as well. Rick mentioned "productizing the external activator for SQL Server 2008". This would mean making the activator part of the SQL Server product, along with the extensive testing and support that go along with it.

That's great news, and a supported, standard, configurable, external activator would make a great addition for SQL Server 2008. Now, about improved broker diagnostic and configuration utilities...and that SQLCLR support library....and improved SSMS support. Those would help things out too (some people are never satisfied).

The companion whitepaper to my "Planning, Implementing, and Administering Scaleout Solutions with SQL Server 2005" whitepaper (see yesterday's post) is available. This whitepaper is called "Internals, Troubleshooting, and Best Practices for use of Scaleout Technologies in SQL Server 2005", with as much about internals as I could cram in 50 pages. Again, I don't have the "main" link; the direct link is here. Enjoy.

I've been working on some whitepapers on scaleout technologies in SQL Server 2005. The first whitepaper is now available; I don't have the main link, but here is the direct link to the doc file on the Microsoft download site. The whitepaper is about the implementation steps when using scaleout technologies like Service Broker, Scalable Shared Database, Query Notiifcations, and Peer-to-Peer Replication and how to choose which technology or combination of technologies is the best fit.

It will be followed by a companion whitepaper about internals and troubleshooting of these same scaleout technologies. I'll let you know when that one's available. Hope you find them useful.

When I first heard about it, I didn't think the DEFAULT contract in Service Broker had the potential to cause confusion. Goes to show what I know. The problem comes up when you assume "no specification" means "use DEFAULT". Not always...

Service Broker contracts indicate which message types can be sent from the conversation initiator, which message types from the conversation target, and which message types from both/either. Service Broker contains a DEFAULT message type (Validation=None) which is a real message type. The DEFAULT contract indicates that the DEFAULT message type (but no other message types) can be sent by ALL.

Here's the possibly confusing bit. On the target side (ie the receiver of the initial message in a conversation), the contract is specified on CREATE SERVICE.

CREATE SERVICE mytarget ON QUEUE myqueue
 (contract1, -- list of supported contracts
  contract2,
  contract3,
  [DEFAULT]  -- we need this, if we want to use DEFAULT
 )

CREATE SERVICE mytarget2 ON QUEUE myqueue2 -- no contract at all supported 
                                                                   -- not even DEFAULT

Leaving out the [DEFAULT] contract here means the target can't use it. You need to specify it.

For the initiator side (ie the sender of the initial message in a conversation) the contract is specified on BEGIN DIALOG.

CREATE SERVICE myinitiator ON QUEUE myqueue_init -- no contract needed here

BEGIN DIALOG @handle
 FROM SERVICE myinitiator
 TO SERVICE 'mytarget'
-- ON CONTRACT [DEFAULT] -- not needed

However, in BEGIN DIALOG you CAN leave out the contract, and this does mean we're using the DEFAULT contract.

Also, sending a message using a message type, leaving out the message type means you're using the [DEFAULT] message.

SEND ON CONVERSATION @handle
-- MESSAGE TYPE [DEFAULT] -- not needed
  ('Hello World')

Got it? DEFAULT message type and contract are the default, except on the target CREATE SERVICE, where its not a default.

 

Categories:
Service Broker

Just got back from the SQLskills Immersion event in Chicago. There were a couple of bonus sessions, with Kimberly doing a high-availability talk for Microsoft customers and our students one evening, and Joe Celko making an appearance on Wedsnesday. Joe spoke on elements of SQL style, and I was able to acquire a signed copy of his new (but not his latest) book "Joe Celko's SQL Programming Style". He's also just released a book on analytics since the style book.

With all the weary smiles at dinner on Thursday, I got the idea that everyone in attendence had a good time and was full to overflowing with the topics we presented. If this sounds interesting to you, there are some spaces in our October event in NYC.

An interesting question that came up at dinner was "how do you motivate use of the Service Broker in SQL Server and how mainstream are the use cases"? Here's how.

If you've ever purchased anything on the web, you'll notice that no matter how popular the website, once you navigate through the catalog, fill out the forms with your personal, shipping, and credit info, the actual order screen is quite quick. You get back an acknowledgement very quickly, but it usually only consists of an "echo" of a subset of the data you entered and an order ID. Also, there is likely a hyperlink where you can check the status of your order. Perhaps an email is sent.

Bet they didn't do a credit check, set up billing, shipping, check inventory, and consult the MRP system for a manufacturing schedule while you were waiting, did they? Most or all of this is done asynchronously, probably with queued messages of some sort. Otherwise, it would be quite a transaction, and if all subsystems weren't on the same instance, a (slower) distributed transaction at that.

Generating an order number, saving the order details (maybe in XML format, for later decomposition into the relevent relational tables), and updating/checking the customer table is much faster. And, if the queueing system is inside the database, your queued messages and database updates will be a fast *local* transaction. If you need to save state, you're already in the "state machine/DBMS", rather than one tier or more away. BTW, if you're using SQL Server's Database Mail feature, the email is also sent asynchronously using Service Broker. Gotta save on that synchronous distributed processing. Else you'll get impatient and push "Buy" again. Or perhaps not return next purchase. 

That's the motivation.

Categories:
Service Broker

There's an interesting article that caught my attention in this month's (July 2006) MSDN magazine by John Mollman about building the MSDN aggregation system. The system uses SQL Server 2005 Service Broker for reliable messaging, activation procedural written in T-SQL, SQLCLR for interactions with the world outside the database and the XML data type and schema support built in to SQL Server.

I found the use of SQL Server Service Broker because of its scalability potential, the data dependent routing implementation, and the plug-in object and interface based provider model most interesting. Check it out.

I just finished my second talk in the “designing and managing scalable systems with SQL Server 2005” webcast series. I got to talk about one of my favorite features in SQL Server 2005, the Service Broker. Some DBA may still think that Service Broker is a developer-only feature, but after you've seen what you can do with Event Notifications (specifically the blocked process event) today, I know you're convinced it also is a substrate for some of the more powerful tools in the DBA toolbox. As well as a great way to help acheive a reliable, scalable system that supports scale out.

I'm posting the broker configuration scripts here, but if these aren't sufficient to walk you through all the points I made in the webcast, feel free to write. I've also given seminars on advanced Service Broker concepts and implementation from a developer and DBA perspective; write if you're interested in learning more.

I referred in the webcast to Roger Wolter (one of the “fathers of Service Broker” 's) weblog, this is listed in the Blogroll at the left. In addition Rushi Desai, Jesús Rodríguez, and Dan Sullivan's blogs have some good info, too. Rushi and Jesús have written some amazing utilities around Service Broker.

Roger's “Where does Service Broker fit in?“ (with respect to MSMQ, Biztalk, and WCF/WWF) blog entry is the Feb 28 entry, but each of these blogs is worth subscribing to...

Here's the scripts from the presentation:

BrokerWebcastScripts.zip (24.36 KB)

Categories:
Service Broker

Service Broker security is the subject of confusion even among people who think they know how it works. Some of the confusion occurs because security was tightened up in the last few CTPs.

I've read in two different places that Service Broker conversations always need to have a master key in the database(s) where the services run. Not so. You don't need a database master key (and this is in RTM) if:

1. Both services (initiator and target) live in the same database
2. You begin the conversation using ENCRYPTION = OFF in the BEGIN DIALOG statement

ENCRYPTED = ON is the default, and you do need a database master key in this case, hence the confusion.

This one is about SQL Server Service Broker. It's not necessarily a cool or sexy feature, but may be the most revolutionary feature in there. The problem with Service Broker is that most people don't get it. They think YAQS (yet another queuing system). It's more than that. It's already used for 3 features inside the server (query notifications, event notifications, and mailer), there could easily be more. A SQL Agent replacement comes to mind. But I digress, this is supposed to be a wish list. If you still don't get it, think harder. Or come talk to me. Or listen. Here's wishes.

SSMS support. Currently only does display functionality. A "route, security, and message testing" piece and configuration would be nice too.

Monolog support. So I won't have to keep explaining why it's "BEGIN DIALOG" but "END CONVERSATION".

Broker support on SQL Server Mobile. For obvious reasons. It could be a discreet subset.

Object model that works for internal activation, external activation, and clients. There's a nice one in engine samples; it should be officially supported. It would be cool if it was design type similar to JMS. Plus extensions.

Supported auto-deployment. For each side of a service. Again, its been done, but not officially supported.

Same (official support) for external activator.

WCF channel. For transactional messages, broker doesn't use DTC. Makes it faster. Faster still when messaging combined with database operations.

HTTP channel. Although that can be built by third parties too.

WCF and WWF assemblies should be able to be marked as "SQL Server safe". Or they'll have to run in the external activator.

Hmmm...many/most of these contained the word "support" somewhere.

More wishes to come.

In this last entry on Service Broker enhancements I inadvertantly referred to the new poison message handling as poison conversation handling. Well, maybe it wasn't so inadvertant. So what's the difference between Service Broker's poison message handling and traditional poison message handling?

A poison message is a fact of life in transactional messaging. When a message is received from a queue, often some database action occurs as part of the same transaction. If the database action fails (say, insert of a row based on a field in the message that happens to be a duplicate key) the message is put back on the queue. Where it is received again... If the database condition that caused the first rollback to happen hasn't been resolved, the transaction will roll back again..and again..hence the term posion message.

Usually poison message handling shunts the message off to a dead letter queue. Where it can be safely ignored while the application goes on. Oh. The problem with this is: suppose the message you are ignoring is a million-dollar order. Or the executive's December check. The database transaction may have rolled back because overflow occurred on an internal variable (especially with extremely large dollar figures). I've personally seen the “executive December check overflows payroll counters“ one, back in the days of COBOL. They used fixed point decimal just like SQL/RDBMSs do today.

Since the primitive concept of Service Broker is the conversation, not the message, the message should not be ignored.
You could lose the million dollar order. Or produce cranky executives. The programmer who designed such an app (and didn't watch the dead letter queue) could be fired. There's something wrong with the conversation, it should be shut down.

The new "posion message handling" actually goes further than that. After 5 receives of the same message, Service Broker shuts down *the queues on both sides of the conversation*. You can recover from this by:
1. Either end the conversation or recieve the message without a rollback
2. And reenable the queues

You can still implement your own poison message handling, using any of the suggestions we described in our "First Look" book. You have 4 retries to do something on your own, before the automatic poison behavior kicks in.

I've been doing some experimenting with the new SQL Server Service Broker features in Feb CTP. You can read about them in the CTPNotes.doc file; I won't repeat the information here. The features are:

1. Improved Endpoint Security - authentication option NONE is not longer supported
2. DEFAULT message type and contract
3. Poison conversation handling

DEFAULT message type and contract came about due to feedback that the DDL to create a simple broker applications consisted of too many pieces. You needed to define MESSAGE TYPEs, CONTRACT, QUEUE, and SERVICE to define the simplest application. The first time this behavior change was described to me (it was some of my students among those who complained about the complexity after all), I thought they were going to loosen things up a bit to work without a contract. But broker uses contracts to enforce conversation integrity. In order to receive a message, a service has to be defined with a contract that's enforced when messages are being put on the queue. No contract, no user messages can be received. Hmmm...how would they do it?

You can now define a broker SERVICE by only defining QUEUE and SERVICE objects. However, the SERVICE must be defined to use a new built-in contract named [DEFAULT]. This contract specifies that a built-in MESSAGE TYPE, also called [DEFAULT], can be sent by either side (by ANY). When you issue a BEGIN CONVERSATION DIALOG without a contract, it uses the [DEFAULT] contract, not NO contract. When you SEND a message without an explicit MESSAGE TYPE it sends the [DEFAULT] message type.

So you're NOT using contract-less and message type-less conversations, you're using a specific contract and message type called [DEFAULT]. You just don't have to define them yourself.

There's a code example is the Feb CTPNotes.doc file (which is why you should always “read the readme file”), try it out for yourself and see.

My cohort, Dan Sullivan, has released the Service Broker Explorer on his Service Broker Developer's Spot website. It a graphic user interface for Service Broker that has some “topology map” features and configuration features and some management features for Service Broker objects. According to Dan:

“It lets you drill into Sevice Broker and add and control elements of Service Broker with a GUI. It's just meant for use to learn about Service Broker, it is not for use in a production system.“

Version 1 of what promises to be a very cool utility.

One of my students last week noticed that using a Service Broker object name (like a CONTRACT, SERVICE, and MESSAGE TYPE name) with the wrong case caused an error message. That's because Service Broker object names are case sensitive by deisgn. Because these identifiers can go over the wire, and you can't predict the collation of the database instance on the other side, they have to go by binary collation. Even when the objects are defined in a single database, you can't assume that's the only place they'll be used. Thanks to Roger Wolter for clarifying this...

Keep this in mind when you define a SERVICE (with the required associated contract) for query notifications or event notifications, as well as in your own broker apps.

I was browsing through some of the SQL Server 2005 code samples today (the ones that come with the product) and came across one that was a really nice idea. It's a library to encapsulate SQL Server Service Broker T-SQL calls in an object model, called ServiceBrokerInterface. Some of the other Service Broker samples are written using it. I've always told folks when they ask about using Service Broker on the client to use raw T-SQL from SqlCommand, but this is a nice wrapper. It can be used to write a client program that processes Service Broker messages or "service programs", that is, a stored procedure inside the server that is used as an activation procedure for a Service Broker queue. Works either way. Kudos to the SQL Server sample-writing team, and that's probably not the only gem in there. Reminded me of...

My all-time favorite SDK sample by far is the OLE DB Rowset Viewer. OLE DB is a fairly overwhelming API to most folks, with a large surface area. You could use Rowset Viewer to not only understand how the OLE DB spec worked, but how provider writers implemented edge case behavior. As an adjunct to coding it yourself, of course. You could work out a complex consumer-task (perhaps involving lots of related OLE DB properties) in the tool, and then go code it up once you "got the answer". Invaluable tool, amazing aid for experimentation.

Theme design by Nukeation based on Jelle Druyts