Deadlocked!: “read committed snapshot” Explained
I just recently read Jeff Atwood’s Deadlocked! article. I just wanted to give some more insight in to the read committed snapshot so that it is not perceived as “magic”. It has some definite advantages when dealing with deadlocks, however if your code relies on row level locking you are not going to be able to use this type of reading in SQL Server.
First lets talk about how you enable it. It is not a transactional isolation level, so if you set it, it will effect your whole database. You have been warned!
alter database [YourDatebaseHere] set read_committed_snapshot on go
Basically what this does is create a snapshot or read-only database of your current results that is separate from your live database. So when you run a SELECT statement, to read your data, you are reading from a read-only copy of your database. When you change your database, it happens on the live database, and then a new copy or snapshot is created for reading against.
Personally I am using it on IdeaPipe, because like most Web 2.0 applications there are a heavy amount of reads and very few updates that effect the row. So chances are if you have a website this will decrease your number of deadlocks. But make sure to test thoroughly before implementing read committed snapshot.
When I was doing my initial research a while ago I found this article talking about how snapshot isolation can bite you where it hurts.
For example, suppose READ COMMITTED SNAPSHOT is not enabled in the database and you want to assign one more ticket to a person, but only if that user does not already have high priority tickets:
BEGIN TRANSACTION UPDATE Tickets SET AssignedTo = 6 WHERE TicketId = 1 AND NOT EXISTS(SELECT 1 FROM Tickets WHERE AssignedTo = 6 AND Priority='High') --- do not commit yetNote that you have not explicitly specified an isolation level, so your transaction runs under the default READ COMMITTED level. If another connection issues a similar update:
UPDATE Tickets SET AssignedTo = 6 WHERE TicketId = 2 AND NOT EXISTS(SELECT 1 FROM Tickets WHERE AssignedTo = 6 AND Priority='High')it will hang in a lock waiting state. Once you commit your first transaction the second one will complete, but it will not assign ticket 2 to user 6, which is the correct behavior as designed.
However if read committed snapshot is enabled on the database the user will end up with two high priority tickets, because the first read happens against a snapshot and the update happens against the live database. So this will obviously cause problems for specifications and business rules that rely on row level locking. So be careful, and make sure you specifically know what is happening with your code before turning this on
Note: Chances are if you are using LINQ you don’t have to worry about the above scenario, however I am not a DBA expert, only a student of the practice. So take what I say with a grain of salt.
Tags: database, LINQ, read committed snapshot, SQL Server

August 25th, 2008 at 11:34 pm
[...] Deadlocked!: “read committed snapshot” Explained – Nick Berardi follows up on Jeff Atwood’s post by talking at more length about the Read Committed Snapshot option, how it works and some of the potential problems when using it. [...]
February 13th, 2010 at 12:31 pm
I agreed with the article and I have enabled READ COMMITTED SNAPSHOT on MS Dynamics 4.0 CRM systems since August 2009 although I am not a developer rather DBA/Architect I know for sure that the application in question code does not relies on row level locking so the bottlenecks has reduced and the performance has been deadly wonderful. Although I was able to reconfigured the subsystem disks the overall performance is 99% good. I would also suggest you test it before deploying on to production.