Isolation levels - Database Engine

  • Comments posted to this topic are about the item Isolation levels - Database Engine

    If everything seems to be going well, you have obviously overlooked something.

    Ron

    Please help us, help you -before posting a question please read[/url]
    Before posting a performance problem please read[/url]

  • That question kicks ***... more please.

  • Shouldn't the where clause of the 3rd statement be "where id = 2"?

  • Excellent question. Fooled me, but then it's fooled 82% of us so far...:P

  • I got this one, but just wanted to clarify a couple of questions in my own mind ....

    (1) If Read Committed Snapshot Isolation had been an option, that would have been correct as well, right?

    (2) The question asks what isolation level is being used by the database. Isn't it more correct to have asked what isolation level is being used by the first connection?

  • Can someone clarify the question and answers here please?

    The question is asking what isolation the database is set to, but the answers are transaction isolation levels.

    Firstly, where is the isolation level for the database set?

    Secondly, I ran a number of tests using the following 2 scripts, with variations.

    Script 1:

    use scratch

    drop table t

    drop table #t

    drop table #u

    create table t (id int, val varchar(20))

    insert t values(2,'Original')

    go

    alter database scratch set allow_snapshot_isolation on

    alter database scratch set read_committed_snapshot off

    go

    set transaction isolation level read committed

    set nocount on

    begin tran

    select Val, getdate() from t where id=2

    declare @i int

    set @i=0

    while @i<5

    begin

    select a.* into #t from sysobjects a, sysobjects b

    select top 1 * into #u from #t

    drop table #t

    drop table #u

    set @i = @i+1

    end

    select Val, getdate() from t where id=2

    rollback tran

    Script 2:

    use scratch

    set transaction isolation level read committed

    set nocount on

    begin tran

    select val, getdate() from t where id=2

    update t set val='gotcha' where id = 2

    select val, getdate() from t where id=2

    declare @i int

    set @i=0

    while @i<5

    begin

    select a.* into #t from sysobjects a, sysobjects b

    select top 1 * into #u from #t

    drop table #t

    drop table #u

    set @i = @i+1

    end

    rollback tran

    Obviously, in each case, the loop is merely to slow down the transaction so that script 2 can start execution while script 1 is running and then script 1 completes before script 2.

    The results were as follows:

    Run 1:

    Script 1:

    alter database scratch set allow_snapshot_isolation on

    alter database scratch set read_committed_snapshot on

    go

    set transaction isolation level snapshot

    Val

    -------------------- -----------------------

    Original 2009-03-05 14:45:28.533

    Original 2009-03-05 14:45:45.800

    Script 2:

    set transaction isolation level snapshot

    val

    -------------------- -----------------------

    Original 2009-03-05 14:45:30.770

    gotcha 2009-03-05 14:45:30.770

    Run 2:

    Script 1:

    alter database scratch set allow_snapshot_isolation on

    alter database scratch set read_committed_snapshot on

    go

    set transaction isolation level read committed

    Val

    -------------------- -----------------------

    Original 2009-03-05 14:49:38.690

    Original 2009-03-05 14:49:55.517

    Script 2:

    set transaction isolation level read committed

    val

    -------------------- -----------------------

    Original 2009-03-05 14:49:40.893

    gotcha 2009-03-05 14:49:40.893

    Run 3:

    Script 1:

    alter database scratch set allow_snapshot_isolation on

    alter database scratch set read_committed_snapshot off

    go

    set transaction isolation level read committed

    Val

    -------------------- -----------------------

    Original 2009-03-05 14:53:53.733

    Original 2009-03-05 14:54:08.673

    Script 2:

    set transaction isolation level read committed

    val

    -------------------- -----------------------

    Original 2009-03-05 14:53:58.280

    gotcha 2009-03-05 14:53:58.280

    Run 4:

    Script 1:

    alter database scratch set allow_snapshot_isolation on

    alter database scratch set read_committed_snapshot off

    go

    set transaction isolation level snapshot

    Val

    -------------------- -----------------------

    Original 2009-03-05 15:12:49.790

    Original 2009-03-05 15:13:09.010

    Script 2:

    set transaction isolation level snapshot

    val

    -------------------- -----------------------

    Original 2009-03-05 15:12:58.633

    gotcha 2009-03-05 15:12:58.633

    In each case the results described in the question were returned. I.e. Script 1 read 'Original', Script 2 updated and read 'gotcha', then Script 1 read 'Original' again.

    As far as I can see it is not possible to tell from the results described either whether the transaction isolation level is snapshot or read committed or whether the database has read_committed_snapshot set on or off.

    Are my scripts wrong or have I missed the point of the question entirely?

    [Edit: Added Run 4, isolation level snapshot with read_committed_snapshot off]

    Derek

  • William Vach (3/5/2009)


    Shouldn't the where clause of the 3rd statement be "where id = 2"?

    A great question that makes you think. But we need to fix the typo in the 3rd statement.

  • It seems that READ COMMITTED gives the same result. Transaction 2 cannot change the row until transaction 1 finishes, but within transaction 2 it sees any updates it has made as done, even though they have not yet been committed so others can see them. This is regardless of the snapshot isolation setting.

  • In an effort to further explain what occurs with the SNAPSHOT and READ COMITTED Isolation using Row versioning - the following quotes were taken from

    http://technet.microsoft.com/en-us/library/ms345124(SQL.90).aspx. The use of italics and bold facing were added by this poster.

    Under the heading

    Snapshot Isolation (Transaction-Level Read Consistency)

    When snapshot isolation is set, it guarantees transaction-level read consistency where every statement within a snapshot isolation transaction sees only committed changes that occurred before the start of the transaction. Effectively, each statement in the transaction sees the same set of data while the data is available for modification outside of this transaction. Concurrent modifications are not prevented and this "snapshot" transaction is unaware of the changes that are made by other transactions. The version "refresh" occurs only in the start of each transaction as long as you run under snapshot isolation

    Under the heading:

    Read Committed Isolation Using Row Versioning (Statement-Level Read Consistency)

    When set, statement-level read consistency guarantees that each statement under read committed isolation sees only committed changes that occurred before the start of the statement. Each new statement within the transaction picks up the most recent committed changes.[/b] In other words, this version of read committed is semantically similar to traditional read committed in that only committed changes are visible, but the timing of when those changes committed differs. Each statement sees the changes that were committed before the statement began instead of when the resource is read.

    In SQL Server 2005, to use row versioning–based isolation, one of the following database options must already be set (and not pending):

    Read committed isolation using row versioning for statement-level read consistency

    Snapshot isolation for transaction-level read consistency

    Hope this clarifies the situation

    If everything seems to be going well, you have obviously overlooked something.

    Ron

    Please help us, help you -before posting a question please read[/url]
    Before posting a performance problem please read[/url]

  • Bitbucket,

    I understand your explation and I read the same information from BOL, etc. That doesn't change the fact that the way you framed the scenario, it makes no difference whether snapshot isolation is on or not, you should get the same result. You specifically state that Transaction 1 makes its second query before Transaction 2 commits, hence it does not see the change Transaction 2 made. Transaction 2, however, will see the change made with itself when it queries the second time, even though it hasn't committed, because it hasn't ended yet.

    This is why a simple answer of READ COMMITTED should be valid.

  • I chose the correct answer because I felt it was most correct. But the way I read it was that if you had READ_COMMITTED_SNAPSHOT set to on, it would produce the same result? But that is not the case?

    From BOL:

    If READ_COMMITTED_SNAPSHOT is set to ON, the Database Engine uses row versioning to present each statement with a transactionally consistent snapshot of the data as it existed at the start of the statement. Locks are not used to protect the data from updates by other transactions.

  • Cliff,

    You are right that READ_COMMITTED_SNAPSHOT being on or off changes outcomes, but just not in the case stated, because of the WAY it is stated. As long as the two overlapping transactions do not commit and also do not end, they will see the original data row values unless they change the values within themselves, a la Transaction 2. The READ_COMMITTED_SNAPSHOT only makes a difference if there is an intervening commit.

  • Wouldn't the last select hang waiting for the pending commit or rollback?

  • No. Only if there was a commit and then it go locked by another transaction. Within a transaction, changes made but not committed are immediately available. The changed row is not locked by the transaction that made the change when it is referencing within itself. The uncommitted row is only unavailable and invisible to other transactions.

  • Does it work this way because the original select and final select are within a transaction? Or does that matter?

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

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