Service Broker Transactions

  • Comments posted to this topic are about the item Service Broker Transactions

  • Good question. Thanks.

    Although I had never used BrokerSend before, I had done something similar on linked servers, ending up in the same error.

  • Good question!

    Explained situation is known as "Uncommitable transaction".

    MS SQL 2008 MCITP x 3
    MS SQL 2012 MCSE x 2

  • Interesting question. I haven't a clue in this area of SQL Server, but it looked like a choice between option 1 and option 3 (option 4 had to be a joke - if it were that it would be famous, but it isn't famous so it isn't that; and option 2 seemed too silly for words). Option 1 was less bizarre, so I chose that and got it wrong.

    The trouble is that even with the explanation and a bit of background reading, I still don't understand it; so obviously I have a lot more reading to do. I guess that means that this QoTD will result in a fair chunk of learning, so it must be a good question.

    Tom

  • Yes, option 4 is a joke.

    This is an uncommittable transaction, you can see outlined in the linked BOL on TRY CATCH with Transactions. I ran into the issue because of an error in a production situation where the massively complicated stored procedure started throwing the "unable to write" exception about 1 time per week. Fortunately a coworker managed to reproduce in house and we were able to identify that the Dialog ID (or conversation id) was what was invalid and causing everything else.

    Working with Service Broker and XML data types can be VERY tricky when dealing with transactions as everything is a severity 16 error which causes the Uncommittable Transaction condition.

  • So, how would you fix the posted code so that the uncommittable transaction message isn't reported?

    I'm curious which COMMIT statement is causing the error. There's a COMMIT statement after the CATCH block inside the proc, and also a COMMIT in the outer transaction.

    I suppose one (or both) of these should check XACT_STATE() before executing?

  • I also don't have any experience in this part of sql but like I Tom I kind of guesses it would be 1 or 3. However answer #4 was just way too funny so I had to pick that to make sure that at least 1 person did. 😀

    Interesting question about a topic I am totally unfamiliar with. Will have to come back and read on this when I get a chance.

    _______________________________________________________________

    Need help? Help us help you.

    Read the article at http://www.sqlservercentral.com/articles/Best+Practices/61537/ for best practices on asking questions.

    Need to split a string? Try Jeff Modens splitter http://www.sqlservercentral.com/articles/Tally+Table/72993/.

    Cross Tabs and Pivots, Part 1 – Converting Rows to Columns - http://www.sqlservercentral.com/articles/T-SQL/63681/
    Cross Tabs and Pivots, Part 2 - Dynamic Cross Tabs - http://www.sqlservercentral.com/articles/Crosstab/65048/
    Understanding and Using APPLY (Part 1) - http://www.sqlservercentral.com/articles/APPLY/69953/
    Understanding and Using APPLY (Part 2) - http://www.sqlservercentral.com/articles/APPLY/69954/

  • Interesting question. I guessed ... and guessed wrong

    ____________________________________________________

    Deja View - The strange feeling that somewhere, sometime you've optimised this query before

    How to get the best help on a forum

    http://www.sqlservercentral.com/articles/Best+Practices/61537
  • Stephanie Giovannini (3/2/2012)


    So, how would you fix the posted code so that the uncommittable transaction message isn't reported?

    I'm curious which COMMIT statement is causing the error. There's a COMMIT statement after the CATCH block inside the proc, and also a COMMIT in the outer transaction.

    I suppose one (or both) of these should check XACT_STATE() before executing?

    The easiest method to fix the error that prompted this question is to check for the Dialog ID (or Conversation ID) in the sys.conversation_endpoints system table (or view?). The error is not at a commit statement, rather at the INSERT INTO dbo.[BrokerErrors] is where it throws the Severity 16, unable to perform operations that write to the log.

    Order of Exceptions:

    1. SEND exception (Severity 16)

    2. INSERT INTO (Severity 16) <-- this is returned to the calling SP/App, aka answer 3

  • Thanks for the question.

    Jason...AKA CirqueDeSQLeil
    _______________________________________________
    I have given a name to my pain...MCM SQL Server, MVP
    SQL RNNR
    Posting Performance Based Questions - Gail Shaw[/url]
    Learn Extended Events

  • Tough question for those of us who don't have experience on this area. I didn't understand quite well the code, nor the papers I found, so i had to basically guess... and got it wrong. 🙁

    "El" Jerry

    "El" Jerry.

    "A watt of Ottawa" - Gerardo Galvan

    To better understand your help request, please follow these best practices.[/url]

  • Thanks for the question. I don't have any experience in this area either.

  • Interesting question. Thanks 🙂

    Service Broker is a facinating technology. I've used it for simple data transfer between servers, to maintaining complex full text indexes (single FT index based on data from multiple tables) and maintaining ACL inheritance in our document management system. The async nature of service brokers opens up endless possibilities. I just LOVE it.

  • venoym (3/2/2012)


    Stephanie Giovannini (3/2/2012)


    So, how would you fix the posted code so that the uncommittable transaction message isn't reported?

    I'm curious which COMMIT statement is causing the error. There's a COMMIT statement after the CATCH block inside the proc, and also a COMMIT in the outer transaction.

    I suppose one (or both) of these should check XACT_STATE() before executing?

    The easiest method to fix the error that prompted this question is to check for the Dialog ID (or Conversation ID) in the sys.conversation_endpoints system table (or view?). The error is not at a commit statement, rather at the INSERT INTO dbo.[BrokerErrors] is where it throws the Severity 16, unable to perform operations that write to the log.

    Order of Exceptions:

    1. SEND exception (Severity 16)

    2. INSERT INTO (Severity 16) <-- this is returned to the calling SP/App, aka answer 3

    Actually, it looks like there are two errors. The first error is the nonexistent dialog id. The second error is attempting to commit an uncommittable transaction after the first error occurs.

    How would the code look if the dialog id error may still occur, but the error handing is fixed?

    I played around a bit, and realized the problem with the uncommittable transaction is not related to Service Broker itself. The following code, based on the order of transactional statements in the procedure, causes the same transaction error:

    create table #errorlog (error nvarchar(50))

    set xact_abort on

    begin transaction

    begin try

    select 3 / 0

    end try

    begin catch

    insert #errorlog values('error')

    end catch

    commit

    The following structure works:

    create table #errorlog (error nvarchar(50))

    set xact_abort on

    begin transaction

    begin try

    select 3 / 0

    commit

    end try

    begin catch

    rollback

    insert #errorlog values('error')

    end catch

    However, in this case the calling code also has a transaction. Putting additional begin/commit around the code results in "The COMMIT TRANSACTION request has no corresponding BEGIN TRANSACTION."

    The SQL that calls the procedure needs to check before committing. Like so:

    create table #errorlog (error nvarchar(50))

    set xact_abort on

    begin transaction

    -- enter procedure

    begin transaction

    begin try

    select 3 / 0

    commit

    end try

    begin catch

    rollback

    insert #errorlog values('error')

    end catch

    -- exit procedure

    if XACT_STATE() = 1 commit

  • Stephanie Giovannini (3/2/2012)


    Actually, it looks like there are two errors. The first error is the nonexistent dialog id. The second error is attempting to commit an uncommittable transaction after the first error occurs.

    How would the code look if the dialog id error may still occur, but the error handing is fixed?

    I played around a bit, and realized the problem with the uncommittable transaction is not related to Service Broker itself. The following code, based on the order of transactional statements in the procedure, causes the same transaction error:

    create table #errorlog (error nvarchar(50))

    set xact_abort on

    begin transaction

    begin try

    select 3 / 0

    end try

    begin catch

    insert #errorlog values('error')

    end catch

    commit

    The following structure works:

    create table #errorlog (error nvarchar(50))

    set xact_abort on

    begin transaction

    begin try

    select 3 / 0

    commit

    end try

    begin catch

    rollback

    insert #errorlog values('error')

    end catch

    However, in this case the calling code also has a transaction. Putting additional begin/commit around the code results in "The COMMIT TRANSACTION request has no corresponding BEGIN TRANSACTION."

    The SQL that calls the procedure needs to check before committing. Like so:

    create table #errorlog (error nvarchar(50))

    set xact_abort on

    begin transaction

    -- enter procedure

    begin transaction

    begin try

    select 3 / 0

    commit

    end try

    begin catch

    rollback

    insert #errorlog values('error')

    end catch

    -- exit procedure

    if XACT_STATE() = 1 commit

    Stephanie, I do like where you are going. I haven't tried exactly what you've done, mainly because I'm several levels deep (the QotD is a trivial example) in nested procedure calls, and in the enterprise environment I'm in I don't have the ability to modify everything that uses this in the manner you've said. It's probably an avenue to explore to prevent nasty messages in processing that I will investigate soon.

    I will throw my 2 cents behind what really needs to be allowed is the ability to do a Checkpoint before the TRY...CATCH and then roll back to it on an exception. It actually makes sense to do that in cases where you are accessing non-local DB items (such as service broker, filesystem, etc.) that way you can do exception handling/logging but maintain the business logic/process. Sadly, this is not available and all Severity 16 exceptions result in an uncomittable transaction.

Viewing 15 posts - 1 through 15 (of 21 total)

You must be logged in to reply to this topic. Login to reply