Learn T-SQL With Erik: Unfortunate Deadlocks Under Read Committed Locking
Video Summary
In this video, I dive into the world of deadlocks in SQL Server, specifically focusing on a unique example that showcases how read queries can deadlock with write queries under the default Read Committed isolation level. This is part of my 24-hour T-SQL course, which includes beginner-level content designed to help you understand and manage these complex issues. I demonstrate this through a simple yet illustrative scenario involving two tables, `deadlock_one` and `deadlock_two`, each with 5,000 rows. By running transactions that update one table while selecting from the other, we observe how SQL Server resolves deadlocks by terminating the transaction that has done less work. This example highlights the importance of understanding isolation levels beyond just read committed, as they can significantly impact performance and stability in your database systems.
Full Transcript
Hey, Erik Darling here with Darling Data. And we are going to continue on with some of the teaser material from my T-SQL course, this one about deadlocks, in which I’m going to talk a little bit about them and show you a fun example of one that is a little bit different from the type of deadlock that you would maybe see in other example, like deadlock examples for beginners. This is, of course, part of the 24 hour, or so, 23, 24 hours of content of beginner material that I have published already. The course is still with a pre-sale price of $250, and we are going to double in value to $500 when the advanced stuff drops after the summer, so, buy now, I guess is your call to action there. Anyway, let’s go talk a little bit about deadlocks. Now, man, you know, one of my least favorite parts of the job is dealing with deadlocks because, well, many of them are very simple and just like, we didn’t have an index there, did we? Like deadlocks can get quite complicated very quickly. Most examples of them, including the one that we’re going to look at today, are part of, like there’s like a two query deadlock, but I’ve run into plenty of situations where there’s a deadlock with a single query on a single table, and you know, you can, either see that from a parallel execution plan or something, and you can even run into them with like a single query, like two, sorry, two queries on a single table, depending on what the query plans look like and what the indexes are doing.
We’ll talk about that in a couple of videos when we talk about, talk a little bit more about how crummy of an isolation level read committed is. But deadlocks are different from blocking because blocking does not represent a situation with a permanent impasse, right? Like, like as soon as whatever query is like leading the blocking finishes or is committed or is rolled back, everything else can make progress.
In deadlocking situations, you have reached this sort of like circular embrace, this like Mobius strip infinity symbol of queries that cannot make, like one or more queries that cannot make progress until something else, like until something intervenes, right? Like there, like there is no hope for this traffic jam until SQL Server wakes up, looks around and says, kaboom, and knocks one of them out of the, the, the executing query queue. So, uh, blocking does beget deadlocks though.
So if you are dealing with deadlocks on your system, you should not just focus on deadlocks. You should focus more, you should also focus more broadly on blocking. Uh, if you’re going to set up, uh, like, you know, uh, an extended event to get deadlocks, you should also set up an extended event to get the block process report because you will, you will capture not like with, like you not only have the deadlocks from the XML deadlock report, but you’ll have like the sort of wider view of all the stuff that’s blocking.
And maybe why things are leading to deadlocks and not just, you know, like staying as like being like, Oh, well, like, you know, we just had this blocking chain and now this thing comes along and screwed everything up. So just sort of generally, uh, SQL Server will choose whatever transaction has done the least amount of work and to kill off when, uh, it wakes up and detects a deadlock. You can, of course, set deadlock priority to a number from negative 10 to positive 10.
If you want to give queries higher or lower priority, as far as who, uh, you know, who will survive the great deadlock wars. So, uh, I’m going to create two tables. One is called deadlock one and one is called deadlock two.
And I’m going to put about 5,000 rows into both of them. And this is just what the tables look like. Now there’s a, you know, pseudo random date and value data in here. And, uh, what we have is just IDs from one to 5,000 in both of them.
That is the, that is the not random part of this at all. Now, what I’m going to show you as far as the deadlocks go is a little bit different from what a lot of other people will show you when they want to show you your first deadlock. Most of the time it’ll be between like, you know, uh, updates or deletes or inserts like modification queries, which is fine.
Modification queries can absolutely deadlock with each other, but under SQL servers, default read committed locking isolation level, which is, uh, as far as I’m concerned, um, one of the most garbage isolation levels to ever exist. Uh, you can see deadlocks just between read queries and write queries. So what I’m going to do is, uh, I’m going to start a transaction.
And these are the two examples that we’re going to use. We have a transaction called T1 that is going to, uh, update, uh, deadlock one where ID equals one, right? So we have a, we have the clustered primary key on ID equals one.
So we seek to this immediately and then we are going to get a count of just from like join both of the tables together on that ID column. Uh, the second query is part of the deadlock is just going to be in a transaction called T2. I didn’t name these for any particular reason other than to differentiate them in the windows.
Uh, and then in this one, we are going to update deadlock two and then get a count from both tables. So we’re kind of doing the same thing in both of these. So in T1, if I come over here and begin the transaction and run the update and in, uh, this window for T2, I just try to run the whole thing.
And then I come back over to T1 and I run the select portion of this. Eventually one of these queries will get knocked off. Which one?
I don’t know. Hey, it was this one. I don’t have to switch windows. Right. But now this is a deadlock that occurred between read queries and write queries. Again, this can happen under, uh, isolation levels, not just read committed. Of course they can, if we were under serializable repeatable read, we would, we could have the same situation occur.
Because the shared locks that this query is that, that the read queries are trying to take are also going to interfere with the exclusive locks that the update queries are trying to take. So not only do we have the updates blocking the reads, but now we have the reads blocking the updates. And now we have a sort of, uh, little, little X shape thing where our shared locks and our, and our X locks are messing with each other.
And they are not having a good time. Someone had to die at this party. And that’s, that is not a good party.
As far as I’m concerned, there are, there are far better ways to throw a fun time than killing someone. Right. It’s not, not, not pleasant. So, uh, this is again, behavior that will happen under isolation levels where, uh, where, uh, read queries and write queries compete with each other. So read committed locking, uh, repeatable read and serializable.
These kinds of deadlocks don’t occur. If you use a real version and isolation level, like read committed snapshot isolation or snapshot isolation, or if you use, uh, an uncategorized isolation level, like read uncommitted. Of course, if you use read uncommitted, you deserve all the pain that you get in life.
And maybe you should go to that kind of party. I don’t know. I’m, I’m, I have mixed feelings about you. Anyway, uh, just a little bit about deadlocks here. Thank you for watching.
I hope you enjoyed yourselves and I will see you over in the next video where we will talk about, uh, exactly why, uh, I have very mixed feelings about this read uncommitted isolation level. So, all right, thank you for watching.
Going Further
If this is the kind of SQL Server stuff you love learning about, you’ll love my training. Blog readers get 25% off the Everything Bundle — over 100 hours of performance tuning content. Need hands-on help? I offer consulting engagements from targeted investigations to ongoing retainers. Want a quick sanity check before committing to a full engagement? Schedule a call — no commitment required.