views:

795

answers:

2

Consider the following SQL:

BEGIN TRAN
SET TRANSACTION ISOLATION LEVEL READ COMMITTED

INSERT Bands
    (  Name  )
SELECT 'Depeche Mode'
UNION
SELECT 'Arcade Fire'

    -- I've indented the inner transaction to make it clearer.

    BEGIN TRAN
    SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

    SELECT *
      FROM Bands

    COMMIT

-- What is the isolation level right here?

UPDATE Bands
   SET Name = 'Modest Mouse'
 WHERE Name = 'Oddest House'

COMMIT

In sum, we start a transaction and set its isolation level to READ COMMITTED. We then do some random SQL and start another, nested transaction. In this transaction we change the isolation level to READ UNCOMMITTED. We then commit that transaction and return to the other.

Now, my guess is that after the inner commit, the isolation level returns to READ COMMITTED. Is this correct?

+2  A: 

I don't think that is correct.

Refer to the remarks here: Set Transaction

Only one of the isolation level options can be set at a time, and it remains set for that connection until it is explicitly changed.

TrickyNixon
this is correct i just tested with sp_lock
Sam Saffron
+2  A: 

You are correct. Interestingly, according to the documentation you linked:

If you issue SET TRANSACTION ISOLATION LEVEL in a stored procedure or trigger, when the object returns control the isolation level is reset to the level in effect when the object was invoked. For example, if you set REPEATABLE READ in a batch, and the batch then calls a stored procedure that sets the isolation level to SERIALIZABLE, the isolation level setting reverts to REPEATABLE READ when the stored procedure returns control to the batch.

So, the bottom line here is that SET TRANSACTION ISOLATION LEVEL has procedure affinity, not transaction affinity (as I had thought).

Awesome!

Gregory Higley
Well that sucks, lol! My C# database API tends to accept open connection objects so I can call multiple functions without opening a new connection each time. This lack of "transaction affinity" means that if I call one database API method from another, and both use a transaction, the nested transaction could alter the transaction isolation level of the caller's transaction. Definitely sucks. WORKAROUND... for any C# method that uses a transaction, simulate procedural affinity for C# transactions with C# code by saving the isolation level (dbcc useroptions) and restoring it before returning!
Triynko