4.3 Non-Repeatable Reads
A non-repeatable read is one in which
data read twice inside the same transaction cannot be guaranteed to
contain the same value. Depending on the isolation
level, another transaction could have nipped in and updated the value
between the two reads.
Non-repeatable reads occur because at lower
isolation levels reading data only locks the data for the duration of
the read, rather than for the duration of the transaction. Sometimes
this behavior might be completely desirable. Some applications may want
to know the absolute, real-time value, even mid transaction, whereas
other types of transactions might need to read the same value multiple
times.
Consider the following example. In Session 1 the transaction reads the data for the top five people from Person.Person
and then waits for five seconds before repeating the step. Execute the
code in Session 1 before flipping to a second session and executing the
code in Session 2 (code file Ch6NonRepeatableReads.sql):
/*SESSION 1*/
USE AdventureWorks2012;
SET TRANSACTION ISOLATION LEVEL
READ COMMITTED;
--REPEATABLE READ;
BEGIN TRANSACTION;
SELECT TOP 5
FirstName
,MiddleName
,LastName
,Suffix
FROM Person.Person
ORDER BY LastName;
WAITFOR DELAY '00:00:05.000';
SELECT TOP 5
FirstName
,MiddleName
,LastName
,Suffix
FROM Person.Person
ORDER BY LastName;
COMMIT TRANSACTION;
/*SESSION 2*/
USE AdventureWorks2012;
BEGIN TRANSACTION;
UPDATE Person.Person
SET Suffix = 'Junior'
WHERE LastName = 'Abbas'
AND FirstName = 'Syed';
COMMIT TRANSACTION;
/*
UPDATE Person.Person
SET Suffix = NULL
WHERE LastName = 'Abbas'
AND FirstName = 'Syed';
*/
Providing you execute the update in Session 2 in time, your results will match Figure 4.
The first read from Session 1, Syed Abbas, had no suffix; but in the
second read he’s now Syed Abbas Junior. The first read, therefore,
hasn’t been repeatable.
You can use the commented-out code in Session 2
to reset the data. Execute this code now. To get a repeatable read,
change the transaction isolation level in Session 1 as indicated here:
SET TRANSACTION ISOLATION LEVEL
--READ COMMITTED;
REPEATABLE READ;
Now rerun Session 1 and Session 2 as
before. You should notice that Session 2 has been blocked from
performing its update until after the transaction has been completed.
The first read in Session 1 is now repeatable. Your results from
Session 1 should now match those in Figure 5.