You are on page 1of 15

Isolation Levels in SQL Server 2005

Isolation Levels
Isolation levels come into play when you need to isolate a resource for a transaction and protect
that resource from other transactions. The protection is done by obtaining locks. What locks need
to be set and how it has to be established for the transaction is determined by SQL Server
referring to the Isolation Level that has been set. Lower Isolation Levels allow multiple users to
access the resource simultaneously (concurrency) but they may introduce concurrency related
problems such as dirty-reads and data inaccuracy. Higher Isolation Levels eliminate concurrency
related problems and increase the data accuracy but they may introduce blocking.

Note that first four Isolation Levels described below are ordered from lowest to highest. The
two subsequent levels are new to SQL Server 2005, and are described separately.

Read Uncommitted Isolation Level

This is the lowest level and can be set, so that it provides higher concurrency but introduces all
concurrency problems; dirty-reads, Lost updates, Nonrepeatable reads (Inconsistent analysis)
and phantom reads. This Isolation Level can be simply tested.

Connection1 opens a transaction and starts updating Employees table.
USE Northwind

BEGIN TRAN

-- update the HireDate from 5/1/1992 to 5/2/1992
UPDATE dbo.Employees
SET HireDate = '5/2/1992'
WHERE EmployeeID = 1

Connection2 tries to read same record.
USE Northwind

SELECT HireDate
FROM dbo.Employees
WHERE EmployeeID = 1

You will see that Connection2 cannot read data because an exclusive lock has been set for the
resource by Connection1. The exclusive locks are not compatible with other locks. Though this
reduces the concurrency, as you see, it eliminates the data inaccuracy by not allowing seeing

uncommitted data for others. That is because it had been set to the default Isolation Level which is Read Committed which in turn disallowed reading uncommitted data. Note that no Isolation Level has been set.results HireDate as 5/2/1992 As you expected. This eliminates dirty-reads but all other concurrency related problems. 'Sales Representative'.UpdateNotes . IF OBJECT_ID(N'dbo. N'P') IS NOT NULL BEGIN DROP PROC dbo. New employee joins and record is made in the table. '03/04/1979'. Imagine the consequences when Connection1 rolls back the transaction but Connection2 makes a decision from the result before the roll back. means default is set.Employees WHERE EmployeeID = 1 -. 'Ms. This is called dirty-reading. HireDate) VALUES ('Lewis'. 'Jane'. You have already seen this. FirstName. Now let’s set the Isolation Level of Connection2 to Read Uncommitted and see. BirthDate. Title.UpdateNotes'. You can expect higher level of concurrency by setting the Isolation Level to Read Uncommitted but you may face all concurrency related problems. Connection2 could not read data before the Isolation Level was set to Read Uncommitted. TitleOfCourtesy. Read Committed Isolation Level This is the default Isolation Level of SQL Server. Assume that the update code has been written as below. Though it stops dirty-reads. USE Northwind SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED SELECT HireDate FROM dbo. Let’s take a simple example that shows Lost Updates. Employee table contains data related to employee. '06/23/2007') This table contains a column called Notes that describes the employee’s education background.Employees (LastName. it may introduce others. Look at the sample used above. Connection2 can see the record that is being modified by Connection1 which is an uncommitted record. Data entry operators fill this column by looking at her/his file.'. USE Northwind INSERT INTO dbo.

The below statement added to hold the transaction for 5 seconds -. 'Jane holds a BA degree in English.UpdateNotes @EmployeeID int. 1) RETURN END COMMIT TRAN END Operator1 makes Connection1 and executes the following query. @Notes ntext AS BEGIN DECLARE @IsUpdated bit BEGIN TRAN SELECT @IsUpdated = CASE WHEN Notes IS NULL THEN 0 ELSE 1 END FROM dbo. WAITFOR DELAY '00:00:5' IF (@IsUpdated = 0) BEGIN UPDATE dbo. EXEC dbo. concurrency related problems such as Lost Updates.' If you query the record after both processes.Consider it is as a different process that do something else.UpdateNotes 15.Employees WHERE EmployeeID = @EmployeeID -.' Within few seconds (in this case. This could be avoided if the record was locked and held as soon as it was identified as a not updated record.UpdateNotes 15. before completing the Operator1’s process.new record -. Repeatable Read Isolation Level . but it has lost its update. you will see that note that was entered by the Operator2 has been set for the record. Nonrepeatable reads and Phantom reads can happen with this Isolation Level. Operator1 made the update and no error messages were returned to it. right after Operator1 started) Operator2 makes Connection2 and executes the same with a different note. 16. 'Jane has a BA degree in English from the University of Washington.Employees SET Notes = @Notes WHERE EmployeeID = @EmployeeID END ELSE BEGIN ROLLBACK TRAN RAISERROR ('Note has been alreasy updated!'. But obtaining and holding a lock is not possible with Read Committed Isolation Level. EXEC dbo. Because of this.END GO CREATE PROCEDURE dbo.

Connection1 obtain and hold the lock on the resource until the transaction completes. avoiding Lost Updates and Nonrepeatable reads. This is because.UpdateNotes END GO CREATE PROCEDURE dbo. EXEC dbo. Since the lock is held until the transaction completes. This stops other transactions accessing the resource. With Connection1.new record Now make two connections and execute below queries just as you did with Read Committed sample. 'Jane holds a BA degree in English.UpdateNotes @EmployeeID int. it does not release the shared lock once the record is read.UpdateNotes 15. Change the Isolation Level of the stored procedure we used for Read Committed sample. It obtains the shared lock for reading and keeps till the transaction is over. it avoids Nonrepeatable Reads too.UpdateNotes'. Note that setting DEADLOCK_PRIORITY to HIGH. Unlike Read Committed.' With Connection2. EXEC dbo. 'Jane has a BA degree in English from the University of Washington. See the code below. SET TRANSACTION ISOLATION LEVEL REPEATABLE READ BEGIN TRAN . N'P') IS NOT NULL BEGIN DROP PROC dbo. SQL Server will throw 1205 error and Connection2 will be a deadlock victim. stopping accessing the resource by others.Employees WHERE EmployeeID = @EmployeeID -.UpdateNotes 15. you can choose the deadlock victim. IF OBJECT_ID(N'dbo. Make sure you set the Note column value back to NULL before executing them. @Notes ntext AS BEGIN DECLARE @IsUpdated bit SET TRANSACTION ISOLATION LEVEL REPEATABLE READ BEGIN TRAN SELECT @IsUpdated = CASE WHEN Notes IS NULL THEN 0 ELSE 1 END FROM dbo. avoiding Lost Updates.' Once you execute the code with Connection2.This Isolation Level addresses all concurrency related problems except Phantom reads.

It guarantees consistency of the information and no Nonrepeatable reads. And no Isolation Level has been set.Employees ADD IsBirthdayAllowanceGiven bit DEFAULT(0) NOT NULL GO Assume that company pays an additional allowance for employees whose birth date fall on current month. getdate(). we add one new table called Allowances and one new column to Employees table called IsBirthdayAllowanceGiven.00 FROM dbo. MonthAndYear. Now let’s take another simple example. avoiding modification from others.Employees WHERE EmployeeID = 10 It reads a record from the Employees table. Allowance) SELECT EmployeeID.Employees WHERE IsBirthdayAllowanceGiven = 0 AND MONTH(BirthDate) = MONTH(getdate()) -. Allowance money) GO -. In this case.additional column that tells whether the birthday allowance is given or not ALTER TABLE dbo.AddBirthdayAllowance END GO CREATE PROC dbo. Note that WAITFOR DELAY has been added hold the transaction for few seconds in order to see the problem related to it.inserts records to allowances table INSERT INTO Allowances (EmployeeID.hold the transaction for 5 seconds -. The below stored procedure inserts allowances for employees whose birth date fall on current month and update employees record. 100.AddBirthdayAllowance'. SELECT Notes FROM dbo. USE Northwind GO -.Consider this is as some other process that takes 5 seconds WAITFOR DELAY '00:00:05' . MonthAndYear datetime. The code for changes are as below. N'P') IS NOT NULL BEGIN DROP PROC dbo.AddBirthdayAllowance AS BEGIN BEGIN TRAN -.table holds allowances CREATE TABLE Allowances (EmployeeID int. IF OBJECT_ID(N'dbo. default applies. The set Isolation Level guarantees the same result for the query anywhere in the transaction because it holds the lock without releasing.

Now open a new connection (let’s name it as Connection1) and run the stored procedure.Employees SET IsBirthdayAllowanceGiven = 1 WHERE IsBirthdayAllowanceGiven = 0 AND MONTH(BirthDate) = MONTH(getdate()) COMMIT TRAN END Before running any queries. Allowance) . In this case. Title.AddBirthdayAllowance'. TitleOfCourtesy.Employees (LastName. 'Ms. BirthDate. N'P') IS NOT NULL BEGIN DROP PROC dbo. 'Sales Representative'.update IsBirthdayAllowanceGiven column in Employees table UPDATE dbo. '07/20/2007') Go back to Connection2. Then open the Employees table and see that how many records have been updated. Once the transaction completed.'. IF OBJECT_ID(N'dbo. This cannot be avoided with default Isolation Level that is Read Committed. Note that no record has been inserted to the Allowances table for Alan. '07/13/1980'.AddBirthdayAllowance AS BEGIN SET TRANSACTION ISOLATION LEVEL REPEATABLE READ BEGIN TRAN -. FirstName. Change the stored procedure and set the Isolation Level as Repeatable Read. MonthAndYear. USE Northwind GO EXEC dbo. the new record is considered as a Phantom record and read of the new record called as Phantom Read. I have one record that stratifies the criteria. open Connection2 and insert a new employee whose birth date falls into current month. query the Allowances table and see. USE Northwind GO INSERT INTO dbo. HireDate) VALUES ('Creg'. You will see a one record that is generated for Michael.AddBirthdayAllowance Immediately. It has updated two. -. make sure at least one employee’s birth date falls on current month. EmployeeId 6: Michael Suyama.AddBirthdayAllowance END GO CREATE PROC dbo. In my Northwind database. not only Michael but Alan.inserts records to allowances table INSERT INTO Allowances (EmployeeID. 'Alan'.

Employees WHERE IsBirthdayAllowanceGiven = 0 AND MONTH(BirthDate) = MONTH(getdate()) Run the clean up code again to bring the Employees table to the original state. SELECT EmployeeID.00 FROM dbo.AddBirthdayAllowance AS BEGIN SET TRANSACTION ISOLATION LEVEL SERIALIZABLE BEGIN TRAN -. Check the result. The behavior of this level is just like the Repeatable Read with one additional feature.AddBirthdayAllowance'. MonthAndYear.inserts records to allowances table INSERT INTO Allowances (EmployeeID. you need to use highest Isolation Level that is Serializable.AddBirthdayAllowance END GO CREATE PROC dbo. It locks not only current records that stratify the filter but new records fall into same filter. Change the stored procedure we used for above sample and set the Isolation Level as Serializable. UPDATE dbo. .Allowances Open two connections again and try the same. It obtains key range locks based on the filters that have been used. IF OBJECT_ID(N'dbo.Employees SET IsBirthdayAllowanceGiven = 0 DELETE dbo. Still the Phantom Reads problem exists.Employees WHERE FirstName = 'Alan' DELETE dbo. In order to avoid this problem. Allowance) SELECT EmployeeID. N'P') IS NOT NULL BEGIN DROP PROC dbo. 100.00 FROM dbo. getdate(). 100.Employees WHERE IsBirthdayAllowanceGiven = 0 AND MONTH(BirthDate) = MONTH(getdate()) Now bring the Employees table to original state. Serializable Isolation Level This is the highest Isolation Level and it avoids all the concurrency related problems. getdate().

These two Isolation Levels provide Optimistic Control and they use Row Versioning. If another transaction that runs under Snapshot Isolation Level requires the same record.Now test the stored procedure and INSERT statement with two connections. ALTER DATABASE Northwind SET ALLOW_SNAPSHOT_ISOLATION ON Let’s look at a simple sample. This is called concurrency control. Under Optimistic Control. USE Northwind BEGIN TRAN . All the Isolation Levels we discussed so far come under a control called Pessimistic Control. Open a new connection (Connection1) and execute query below. Since there is a performance impact with Snapshot Isolation Level it has been turned off by default. SQL Server does not hold locks but once read. You can enable it by altering the database. check for inconsistency for next read. it can be taken from the version store. Snapshot Isolation Level The Snapshot Isolation Level works with Row Versioning technology. You will notice that INSERT operation is blocked until Connection1 completes the transaction. Whenever we set the Isolation Level to a transaction. The impact is explained below with the sample. in addition to that it allows multiple updates for same resource by different transactions concurrently. Run the clean up code again and drop the new table Allowances and added column IsBirthdayAllowanceGiven in the Employees table. avoiding Phantom Reads. The other concurrency control is Optimistic Control. Whenever the transaction requires a modification for a record. The two newly introduced Isolation Levels with SQL Server 2005 are Snapshot and Read Committed Snapshot. SQL Server locks the resource until user performs the action she/he needs and then release for others. The Pessimistic control. Make sure you have enabled Snapshot Isolation Level in the database before running below query. This Isolation Level prevents all concurrency related problems just like Serializable Isolation Level. SQL Server makes sure that the transaction is not disturbed by other transactions. SQL Server first stores the consistence version of the record in the tempdb.

You will see one record in the store. . Note that HireDate of the employee is 05/01/1992 not 05/02/1992. SELECT * FROM sys. results longer link list in the version store. Now set the Isolation Level of the Connection2 as Snapshot and try to retrieve the record. SQL Server stores version of the record. If another transaction starts changing same record. COMMIT TRAN Again open the Connection2 and execute the query. SET TRANSACTION ISOLATION LEVEL SNAPSHOT BEGIN TRAN SELECT * FROM dbo.Employees SET HireDate = '5/2/1992' WHERE EmployeeID = 1 Now open the second connection (Connection2) and try to retrieve the same record. Connection2 still gets the older record. Use below dynamic management view for retrieving versions stored in the store. Committing the transaction in Connection2 will remove the reference for the first version and the first version in the store will be removed from separate clean-up process.Employees WHERE EmployeeID = 1 This returns record from the store that was the last consistence version of the record.Employees WHERE EmployeeID = 1 As you have seen with examples discussed under other levels. another version will be stored and goes on. This is because it was the consistence record in the version store when the Connection2 started the transaction and the same version is read during the transaction. the record cannot be retrieved. Note that even though the Connection1 has committed the change.dm_tran_version_store. -.update the HireDate from 5/1/1992 to 5/2/1992 UPDATE dbo. SQL Server keeps this version of the record until no reference for it. Now go back to the Connection1 and commit the transaction. Maintaining longer link list and traversing through list will impact the performance. Since we have enabled Snapshot Isolation Level in the database. SELECT * FROM dbo.

USE Northwind GO SET TRANSACTION ISOLATION LEVEL SNAPSHOT BEGIN TRAN SELECT * FROM dbo. or insert the row that has been modified or deleted by another transaction. Note that the current transaction still runs. USE Northwind BEGIN TRAN -. One transaction reads a record from the version store and later tries to update the record.Employees SET HireDate = '5/2/1992' WHERE EmployeeID = 1 Open the second connection (Connection2) and read the same record. Whenever you execute the UPDATE statement. it throws an error.Employees WHERE EmployeeID = 1 Go back to Connection1 and commit the transaction. Note the Isolation Level. delete. . Another transaction updates the same record before previous transaction’s update.Employees' directly or indirectly in database 'Northwind' to update. Open a connection (Connection1) and run the below query. It is Conflict Detection. Retry the transaction or change the isolation level for the update/delete statement.There is another great feature with Snapshot Isolation Level.update the HireDate from 5/1/1992 to 5/2/1992 UPDATE dbo. You cannot use snapshot isolation to access table 'dbo. This conflict detects by the SQL Server and aborts the previous transaction. SQL Server detects the modification that has been done by Connection1 in between read and write.Employees SET HireDate = '5/3/1992' WHERE EmployeeID = 1 Snapshot isolation transaction aborted due to update conflict. COMMIT TRAN Go back to Connection2 and try to update the record. The update statement causes to add the current consistence version to the version store. UPDATE dbo.

The value for the HireDate will be the last consistence value that is 05/01/1992. Go back to Connection1 and commit the transaction.Employees SET HireDate = '5/2/1992' WHERE EmployeeID = 1 This makes a last consistence version in the version store. Unlike Snapshot. COMMIT TRAN . Read Committed Snapshot Isolation Level This is the new implementation of the Read Committed Isolation Level. enable the Isolation Level. USE Northwind BEGIN TRAN -. First. this level is not recommended for a database that has many updates. USE Northwind GO BEGIN TRAN SELECT * FROM dbo.update the HireDate from 5/1/1992 to 5/2/1992 UPDATE dbo. The Read Committed Snapshot differs from Snapshot in two ways. It has to be set not at session/connection level but database level. Though this Isolation Level has some great advantageous.Employees WHERE EmployeeID = 1 You get a record from the version store. Now open the second connection (Connection2) and try to retrieve the record. Read Committed Snapshot is Optimistic whereas Read Committed is Pessimistic.Once the conflict is detected. This is suitable for database that is mainly used for read data with occasional updates. it always returns latest consistence version and no conflict detection. ALTER DATABASE Northwind SET READ_COMMITTED_SNAPSHOT ON Now open a new connection (Connection1) and run the below query. The only different between Read Committed and Read Committed Snapshot is. Let’s test this out. it terminates the transaction in Connection2.

there will be no impact for performance like Snapshot but all the concurrency related problems except dirty reads can happen. Commit the Connection2 transaction too. . or wait until you write new code to take advantage of this feature. execute the SELECT statement again. all statements see a snapshot of the data as it existed at the start of the transaction. The biggest benefit of this isolation level is that it gives you a transactionally consistent view of your data. you have to either modify your old code. but also must modify your current code so that the TRANSACTION ISOLATION LEVEL SNAPSHOT isolation level is set for it. but it is based at the transaction level. let’s summarize. When the ALLOW_SNAPSHOT_ISOLATION is turned on at the database level and the TRANSACTION ISOLATION LEVEL SNAPSHOT isolation level is turned on for the transaction (using the SET command). To take advantage of ALLOW_SNAPSHOT_ISOLATION. you not only have to turn it on at the database level. Unlike Snapshot the latest consistence is returned that has the HireDate as 05/02/1992. Any data read will be the most recent committed version of the data. Since this is a new feature of SQL Server 2005.In Connection1. not the statement level. Dirty Lost Nonrepeatable Phantom Concurrency Conflict Reads Updates reads reads model Detection Read Yes Yes Yes Yes Pessimistic No Uncommitte d Read No Yes Yes Yes Pessimistic No Committed Repeatable No No No Yes Pessimistic No Read Serializable No No No No Pessimistic No Snapshot No No No No Optimistic Yes Read No Yes Yes Yes Optimistic No Committed Snapshot ALLOW_SNAPSHOT_ISOLATION is similar to READ_COMMITTED_SNAPSHOT. Since the maintaining old versions are not necessary with this level. Finally. The below table depicts importance points of each level.

READ_COMMITTED_SNAPSHOT is generally recommended over ALLOW_SNAPSHOT_ISOLATION for the following reasons: • It uses less tempdb space. If you SET a different isolation level. . This means that all transactions in this database will implement row versioning. To turn these options on and off at the database level. AND you must use the SET command to specify TRANSACTION ISOLATION LEVEL SNAPSHOT for the connection. Keep the following in mind: • To use either of these two new isolation levels. the two new isolation levels are implemented differently.Unlike the four older isolation levels. then this setting must be turned on at the database level. Below are some examples: ALTER DATABASE AdventureWorks SET READ_COMMITTED_SNAPSHOT ON ALTER DATABASE AdventureWorks SET READ_COMMITTED_SNAPSHOT OFF ALTER DATABASE AdventureWorks SET ALLOW_SNAPSHOT_ISOLATION ON ALTER DATABASE AdventureWorks SET ALLOW_SNAPSHOT_ISOLATION OFF While both of these new isolation levels have pros and cons. then any statement or transaction that is SET to (or defaults to) READ_COMMITTED will use row versioning. • You can turn on either READ_COMMITTED_SNAPSHOT or ALLOW_SNAPSHOT_ISOLATION at the database level. then that setting overrides the default behavior. • If READ_COMMITTED_SNAPSHOT is turned on. which can be a little confusing at first. or you can turn on both READ_COMMITTED_SNAPSHOT and ALLOW_SNAPSHOT_ISOLATION at the database level. you use the ALTER DATABASE command. • If you want to take advantage of ALLOW_SNAPSHOT_ISOLATION. they have to be turned on at the database level.

If your database is very data modification intensive. While the main advantage of these new isolation levels is better overall performance. • It is not vulnerable to update conflicts. snapshot_isolation_state_desc. They include: • Increased use of the tempdb.dm_db_session_space_usage .dm_db_file_space_usage • sys. you can quickly determine the status of the database-wide setting by running this statement: SELECT name. They include: • sys. then these isolation levels may not be appropriate for you. • It works with distributed transactions. • Update transactions will be slowed down because of the need to version data rows as updates are made.databases This produces results like the following: In addition. If you decide to use one or both of these two new isolation levels. • They should not be used if you expect update conflicts in you data (more than one connection will update the same data at the same time). is_read_committed_snapshot_on FROM sys. there are a series of DMVs (dynamic management views) that you can watch to monitor the effect of using these isolation levels. You may want to watch its size more closely. there can be some downsides to using them. • It works with most pre-existing applications. and also place it on an isolated disk or array for better performance.

there is a lot to learn about these new isolation levels. You can find even more information in Books Online. there are a number of performance counters you can also use to monitor performance related to these new isolation levels.dm_tran_active_snapshot_database_transactions • sys. .dm_tran_current_transaction • sys. this one may help performance. • sys.dm_tran_top_version_generators • sys.dm_tran_current_snapshot In addition to the above DMVs. be sure you thoroughly test them in a test database before rolling them out to production. or it may hurt performance.dm_tran_version_store • sys. If you feel you might be able to take advantage of one or both of these options.dm_db_task_space_usage • sys. It is your job as the DBA to sort this out for your particular database applications. Like most performance enhancement tips. They include: • Free Space in tempdb (kb) • Version Store Size (kb) • Version Generation Rate (kb/s) • Version Cleanup Rate (KB/s) • Version Store Unit Creation • Version Store Unit Truncation • Update Conflict Ratio • Longest Transaction Running time • Transactions • Snapshot Transactions • Update Snapshot Transactions • NonSnapshot Version Transactions As you can see.dm_tran_transactions_snapshot • sys.