Showing posts with label bol. Show all posts
Showing posts with label bol. Show all posts

Friday, March 30, 2012

Internal Activation Best Practices?

I am looking for an example of a SP that shows the best practices for internal activation? In BOL this topic describes the typical patter for reading messages from a queue. What is the typical pattern for reading messages from a queue using an internally activated SP? Do we still need to loop (considering the message arrival actually fired the sp)?

Any advice provided would be helpful.

Thanks!

Yes, you should still loop. If you don't loop, you risk getting at maximum only one activated procedure, instead of the value set for max_queue_readers. If a procedure is launched and it exits imedeatly (expecting to be launched again), the activation algorithm timers will be reset by this event, so the activation will never reach the point when it has to launch a new instance of the procedure.

The Activation algorithm is described here: http://msdn2.microsoft.com/en-us/library/ms171601.aspx

Another important reason why you should loop is the need to batch commit. If your procedure RECEIVEs one message, process it and commits, you won't be able to scale. Even the best tuned system will only be able to process only tens of messages per second, maybe a best a few hundred. You have to batch several tens, even hundreds, of messages in one transaction, to be able to process thousands of messages per second. The trick here is to avoid holding up a transaction in wait for a message. That is, if you have a batch pending, do a plain RECEIVE, not a WAITFOR(RECEIVE). If the RECEIVE returns empty, commit the pending batch and only then do the WAITFOR(RECEIVE).

Do linger few seconds in your loop before exiting. That is, have a WAITFOR (RECEIVE), TIMEOUT 1000 (or 2000) to drive the loop. This way, the activated procedure will be already started if a new message arrives quickly after you just drained the queue. Don't linger to much, as you're keeping a server thread occupied.

Don't fake an empty queue. That is, don't have a RECEIVE ... WHERE that will return empty rowset even when there are messages in the queue. This will fool the activation algorithm to think that you drained the queue, and will prevent new instances of the procedure to be launched.

Activated procedures have a different execution context than user connection launched procedures. They are under an EXECUTE AS USER context, thus under all the restrictions described here: http://msdn2.microsoft.com/en-us/library/ms188304.aspx. So try to design the procedure avoiding the need to access resources outside the database. If you must, then you'll have to either turn on the trustworthy bit on the database, or folllow these complex steps: http://blogs.msdn.com/remusrusanu/archive/2006/03/07/545508.aspx

Do make sure your procedure handles the system message types:
http://schemas.microsoft.com/SQL/ServiceBroker/Error
http://schemas.microsoft.com/SQL/ServiceBroker/EndDialog
http://schemas.microsoft.com/SQL/ServiceBroker/DialogTimer

Don't rollback intentionally in your procedure. It will trigger the poison message detection and disable your queue.

Do experiment with various ways of writing the RECEIVE loop, e.g.:
- TOP (1) into T-SQL variables
- INTO @.tableVariable and open cursor over @.tableVariable
- CLR procedure and RECEIVE a whole resultset into a SqlDataReader
See which one gives the bets performance for your environment. Some are better when you're likely to have always one message returned, some are better when you're likely to have many messages returned by RECEIVE. Consider that RECEIVE returnes only messages on one conversation_group.

HTH,
~ Remus

|||

I has been brought to my attention that one of my comments is wrong:

If a procedure is launched and it exits imedeatly (expecting to be launched again), the activation algorithm timers will be reset by this event, so the activation will never reach the point when it has to launch a new instance of the procedure.

This is incorrect, the exiting the procedure does not reset the timer and the activation algorithm works as expected in these conditions: the max_queue_readers is reached.

HTH,
~Remus

|||Great info Remus!

Internal Activation Best Practices?

I am looking for an example of a SP that shows the best practices for internal activation? In BOL this topic describes the typical patter for reading messages from a queue. What is the typical pattern for reading messages from a queue using an internally activated SP? Do we still need to loop (considering the message arrival actually fired the sp)?

Any advice provided would be helpful.

Thanks!

Yes, you should still loop. If you don't loop, you risk getting at maximum only one activated procedure, instead of the value set for max_queue_readers. If a procedure is launched and it exits imedeatly (expecting to be launched again), the activation algorithm timers will be reset by this event, so the activation will never reach the point when it has to launch a new instance of the procedure.

The Activation algorithm is described here: http://msdn2.microsoft.com/en-us/library/ms171601.aspx

Another important reason why you should loop is the need to batch commit. If your procedure RECEIVEs one message, process it and commits, you won't be able to scale. Even the best tuned system will only be able to process only tens of messages per second, maybe a best a few hundred. You have to batch several tens, even hundreds, of messages in one transaction, to be able to process thousands of messages per second. The trick here is to avoid holding up a transaction in wait for a message. That is, if you have a batch pending, do a plain RECEIVE, not a WAITFOR(RECEIVE). If the RECEIVE returns empty, commit the pending batch and only then do the WAITFOR(RECEIVE).

Do linger few seconds in your loop before exiting. That is, have a WAITFOR (RECEIVE), TIMEOUT 1000 (or 2000) to drive the loop. This way, the activated procedure will be already started if a new message arrives quickly after you just drained the queue. Don't linger to much, as you're keeping a server thread occupied.

Don't fake an empty queue. That is, don't have a RECEIVE ... WHERE that will return empty rowset even when there are messages in the queue. This will fool the activation algorithm to think that you drained the queue, and will prevent new instances of the procedure to be launched.

Activated procedures have a different execution context than user connection launched procedures. They are under an EXECUTE AS USER context, thus under all the restrictions described here: http://msdn2.microsoft.com/en-us/library/ms188304.aspx. So try to design the procedure avoiding the need to access resources outside the database. If you must, then you'll have to either turn on the trustworthy bit on the database, or folllow these complex steps: http://blogs.msdn.com/remusrusanu/archive/2006/03/07/545508.aspx

Do make sure your procedure handles the system message types:
http://schemas.microsoft.com/SQL/ServiceBroker/Error
http://schemas.microsoft.com/SQL/ServiceBroker/EndDialog
http://schemas.microsoft.com/SQL/ServiceBroker/DialogTimer

Don't rollback intentionally in your procedure. It will trigger the poison message detection and disable your queue.

Do experiment with various ways of writing the RECEIVE loop, e.g.:
- TOP (1) into T-SQL variables
- INTO @.tableVariable and open cursor over @.tableVariable
- CLR procedure and RECEIVE a whole resultset into a SqlDataReader
See which one gives the bets performance for your environment. Some are better when you're likely to have always one message returned, some are better when you're likely to have many messages returned by RECEIVE. Consider that RECEIVE returnes only messages on one conversation_group.

HTH,
~ Remus

|||

I has been brought to my attention that one of my comments is wrong:

If a procedure is launched and it exits imedeatly (expecting to be launched again), the activation algorithm timers will be reset by this event, so the activation will never reach the point when it has to launch a new instance of the procedure.

This is incorrect, the exiting the procedure does not reset the timer and the activation algorithm works as expected in these conditions: the max_queue_readers is reached.

HTH,
~Remus

|||Great info Remus!

Friday, February 24, 2012

Integration Services in BOL: Is this all I get?

Short answer
NO, the beta or CTP Books Online that you're using is not all there's going to be. Make sure that you watch for the Web release of BOL that will drop around the time that SQL Server 2005 hits the streets! Read more to understand why.

More information
SQL Server 2005 is going to be released simultaneously in 8 or 9 languages. Since the documentation team had to lock down early to allow time for translation, the version of Books Online that you'll get on the CD in the box is going to be several months old. Think of the BOL in the box as Version 0.9, while Version 1.0 will be the RTM Web release. Meanwhile we're working non-stop to update, improve, and add to the Integration Services content in Books Online.

Remember that the BOL feedback links are your most direct route to improved content!

-Doug

Doug,
Are we going to be able to sync our local install with the web release?

-Jamie|||Jamie,

If you mean, will you see updated content silently downloaded on a topic-by-topic basis in your existing BOL installation, unfortunately, no. BOL and the Microsoft Help 2.0 technology that we rely on don't currently support that. The Web release around RTM that I mentioned will simply be a complete new BOL installation...and yes, a rather sizeable download.

We will, at least, be flagging content that has changed significantly so that you won't have to scan all the sections that interest you with the hope of coming across some new tidbit of information.

Best regards,

-Doug