March 4, 2009 at 10:09 pm
Comments posted to this topic are about the item Isolation levels - Database Engine
March 5, 2009 at 4:13 am
That question kicks ***... more please.
March 5, 2009 at 5:34 am
Shouldn't the where clause of the 3rd statement be "where id = 2"?
March 5, 2009 at 6:18 am
Excellent question. Fooled me, but then it's fooled 82% of us so far...:P
March 5, 2009 at 7:08 am
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?
March 5, 2009 at 8:10 am
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
March 5, 2009 at 8:36 am
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.
March 5, 2009 at 9:17 am
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.
March 5, 2009 at 12:01 pm
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
March 5, 2009 at 12:24 pm
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.
March 5, 2009 at 12:25 pm
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.
March 5, 2009 at 12:35 pm
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.
March 5, 2009 at 12:39 pm
Wouldn't the last select hang waiting for the pending commit or rollback?
March 5, 2009 at 12:45 pm
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.
March 5, 2009 at 12:56 pm
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