Transactions 2

  • Thank you great question.

    Plus extra thanks to Hugo for the link

    Hugo Kornelis (5/23/2012)


    For a very complete discussion on this subject, read http://www.sommarskog.se/error_handling_2005.html.

  • Thanks for the question. Mission accomplished for me = learned something.

    [font="Verdana"]Please don't go. The drones need you. They look up to you.[/font]
    Connect to me on LinkedIn

  • Having the default setting to OFF basically break transactions and is a *bug* in SQL Server.

    Explicit transactions should be exactly that, explicit. This stupidity is exactly the kind of thing that will cause nearly untraceable bugs in code. What were they thinking?

    However, kudos for pointing this out, at least now it won't catch me...

    Member of SPCP -- Society for the Prevention of Cruelty to Programmers

  • I agree with some of the other posts that express frustration that this is the default setting that seems rather contrary to an explicit transaction.

    So the take away here is that whenever you need to declare an explicit transaction you should include SET XACT_ABORT ON before proceeding.

    I have to remember that one, thanks.

  • Neil Thomas (5/23/2012)


    So that means that when xact_abort is set to off then

    BEGIN TRANSACTION

    ...

    COMMIT TRANSACTION

    does not do as expected.

    What's the default setting on a fresh install of SQL?

    But this would also work as though xact_abort is on 🙂

    BEGIN try

    begin TRANSACTION

    INSERT qotd2(col1,col2,col3) VALUES (1,'x','some')

    INSERT qotd2(col1,col2,col3) VALUES (1,'Y','thing')

    INSERT qotd2(col1,col2,col3) VALUES (2,'Z','or other')

    COMMIT

    END TRY

    BEGIN CATCH

    ROLLBACK

    END catch

    SELECT * FROM qotd2



    --Mark Tassin
    MCITP - SQL Server DBA
    Proud member of the Anti-RBAR alliance.
    For help with Performance click this link[/url]
    For tips on how to post your problems[/url]

  • Daniel Bowlin (5/23/2012)


    I agree with some of the other posts that express frustration that this is the default setting that seems rather contrary to an explicit transaction.

    So the take away here is that whenever you need to declare an explicit transaction you should include SET XACT_ABORT ON before proceeding.

    I have to remember that one, thanks.

    So just remember the Begin transaction statement is spelled

    SET XACT_ABORT ON

    BEGIN TRANSACTION

    :hehe:

  • roger.plowman (5/23/2012)


    Having the default setting to OFF basically break transactions and is a *bug* in SQL Server.

    Explicit transactions should be exactly that, explicit. This stupidity is exactly the kind of thing that will cause nearly untraceable bugs in code. What were they thinking?

    They were probably thinking that explicit transactions usually come with explicit error handling. For instance using the TRY CATCH pattern, as shown by mtassin.

    Daniel Bowlin (5/23/2012)


    So the take away here is that whenever you need to declare an explicit transaction you should include SET XACT_ABORT ON before proceeding.

    Hmm, no. Only when you declare an explicit transaction AND you don't want to add explicit error handling AND you are fine with the default error handling with XACT_ABORT set to ON. There are lots of situations where you would not want that.


    Hugo Kornelis, SQL Server/Data Platform MVP (2006-2016)
    Visit my SQL Server blog: https://sqlserverfast.com/blog/
    SQL Server Execution Plan Reference: https://sqlserverfast.com/epr/

  • mtassin (5/23/2012)


    But this would also work as though xact_abort is on 🙂

    BEGIN try

    begin TRANSACTION

    INSERT qotd2(col1,col2,col3) VALUES (1,'x','some')

    INSERT qotd2(col1,col2,col3) VALUES (1,'Y','thing')

    INSERT qotd2(col1,col2,col3) VALUES (2,'Z','or other')

    COMMIT

    END TRY

    BEGIN CATCH

    ROLLBACK

    END catch

    SELECT * FROM qotd2

    No, it would not. With XACT_ABORT set to ON, the final SELECT statement would never be executed. XACT_ABORT causes the batch to be terminated on an error.


    Hugo Kornelis, SQL Server/Data Platform MVP (2006-2016)
    Visit my SQL Server blog: https://sqlserverfast.com/blog/
    SQL Server Execution Plan Reference: https://sqlserverfast.com/epr/

  • Hugo Kornelis (5/23/2012)


    Only when you declare an explicit transaction AND you don't want to add explicit error handling AND you are fine with the default error handling with XACT_ABORT set to ON. There are lots of situations where you would not want that.

    Most situations I'd have thought. Wouldn't youy normally want unexpected errors of this sort to be logged somewhere? Using XACT_ABORT won't do this, but explicit error handling will if you remember to code it for course).

  • Hugo Kornelis (5/23/2012)


    I guess that depends on the expectation. The code in this QotD contains no error-handling and an unconditional COMMIT statement.

    My expectation is that those two conditions never exist in production code.

    Either begin a transaction and handle errors correctly (which might be to rollback) or don't incur the overhead of the transaction in the first place.

    Our typical ad-hoc queries have the commit before the begin transaction and commented out so it can't be run with a batch of code. Instead it is run after successful execution, with the understanding that any error in a batch means something was wrong so rollback.

    All new hires are taught that "begin transaction" is part of a delete statement per the CYA rule. Also any time 'begin transaction' is used, you are not allowed to leave for lunch until after commit or rollback. (that was a hard-won lesson)

    Is there ever a case where row-level failures are acceptable and a batch should be committed regardless? I understand ETL processes might have some reason to not insert already-existing rows, but shouldn't that be handled explicitly rather than ignoring key/constraint failures? How would you explain to management or a coworker why this is a Bad Thing?

  • Hugo Kornelis (5/23/2012)


    mtassin (5/23/2012)


    But this would also work as though xact_abort is on 🙂

    BEGIN try

    begin TRANSACTION

    INSERT qotd2(col1,col2,col3) VALUES (1,'x','some')

    INSERT qotd2(col1,col2,col3) VALUES (1,'Y','thing')

    INSERT qotd2(col1,col2,col3) VALUES (2,'Z','or other')

    COMMIT

    END TRY

    BEGIN CATCH

    ROLLBACK

    END catch

    SELECT * FROM qotd2

    No, it would not. With XACT_ABORT set to ON, the final SELECT statement would never be executed. XACT_ABORT causes the batch to be terminated on an error.

    Sorry, I worry more about what goes into or out of a table... the select statement at the end was an after thought. If the intention was that none of the data goes in if one of the inserts fails, then the try/catch blocks above also give that result.



    --Mark Tassin
    MCITP - SQL Server DBA
    Proud member of the Anti-RBAR alliance.
    For help with Performance click this link[/url]
    For tips on how to post your problems[/url]

  • mtassin (5/23/2012)


    Sorry, I worry more about what goes into or out of a table... the select statement at the end was an after thought. If the intention was that none of the data goes in if one of the inserts fails, then the try/catch blocks above also give that result.

    Yes, I understand.

    My point is that using a TRY ... CATCH block is better than using XACT_ABORT, because it gives you much more control over how errors are handled and what information is returned to the client.


    Hugo Kornelis, SQL Server/Data Platform MVP (2006-2016)
    Visit my SQL Server blog: https://sqlserverfast.com/blog/
    SQL Server Execution Plan Reference: https://sqlserverfast.com/epr/

  • Thanks for the question!

  • Hugo Kornelis (5/23/2012)


    mtassin (5/23/2012)


    Sorry, I worry more about what goes into or out of a table... the select statement at the end was an after thought. If the intention was that none of the data goes in if one of the inserts fails, then the try/catch blocks above also give that result.

    Yes, I understand.

    My point is that using a TRY ... CATCH block is better than using XACT_ABORT, because it gives you much more control over how errors are handled and what information is returned to the client.

    Oh I agree... We got TRY/CATCH 4 versions of SQL ago (2005, 2008, 2008R2, 2012 by my count)

    It wasn't until recently that we've really started to use it more to its fullest... Too many years with SQL 2000 makes using new features tough.... 🙂



    --Mark Tassin
    MCITP - SQL Server DBA
    Proud member of the Anti-RBAR alliance.
    For help with Performance click this link[/url]
    For tips on how to post your problems[/url]

  • Nakul Vachhrajani (5/22/2012)


    Good question with a couple of learning points.

    1. By default SQL does not abort the entire transaction if it encounters a statment-level failure. In this case, the primary key violation is a statement level failure and hence, only the statement terminated, not the entire transaction

    If the requirement is to cause a failure of the entire transaction (i.e. abort), then the following SET option needs to be set to ON:

    SET XACT_ABORT ON

    Setting XACT_ABORT to ON will cause SQL Server to abort the transaction even if it encounteres the statement level failure.

    2. Referring one of my blog posts, row constructors (introduced in SQL Server 2008) process the entire batch at once. Hence, had this example used row constructors, the correct answer would have been 0 rows affected (Reference post: http://beyondrelational.com/modules/2/blogs/77/Posts/14434/0159-sql-server-row-constructors-triggers-process-the-entire-batch-at-once.aspx)

    Thank-you!

    THIS should have been the explanation. The explanation given for the question explains nothing.

Viewing 15 posts - 16 through 30 (of 56 total)

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