I was running a proc inside a cursor. After a lot of successful iterations, I got this:
Transaction (Process ID 104) was deadlocked on lock | communication buffer resources with another process and has been chosen as the deadlock victim. Rerun the transaction.
I am not posting the full details, so I don't expect a fine grained debugging answer. The facts:
select
(I saw the running query from dm exec requests)If I am not mistaken on my 2 points, is it ever possible to have a deadlock? Wouldn't the deadlock require all of the involved users of a resource to be doing write operations on them, which would create a cycle in the resource request graph? I understand a timeout error in a select
, but cannot understand a deadlock. What am I missing?
An update:
I abandoned further debugging because I noticed that an index I thought existed didn't. When it was created, the performance was OK.
However, in hopes to keep this useful and hopefully come up with an answer, here is some more things I investigated, some facts, and thoughts on comments:
First, the SQL Server version is 2008. I understand this is not supported. I am in no position to make recommendations, much less update the server though.
I found Jeroen Mostert's comment interesting. How much is "the past"? I noticed in sys.dm_os_waiting_tasks
the session being blocked by itself multiple times with wait type CXPACKET. I did some searching around, but option(maxdop 1)
did not solve the problem. However, remember the index that did not exist which would cause abysmal performance. Could it be that there was correct parallelism appended, but the operations were too many? Still, I also witnessed a huge dm_exec_requests.wait_time
. So, even though the query was bad, I am led to believe that there were strange (dead)locks around.
If an answer/comment comes up with specific queries/steps to do to trace the problem, I'll be happy to recreate it.
It is possible for a SELECT to cause a deadlock if someone else is using the table.
This example is ripped almost 100% from Brent Ozar's video on deadlocks, but changed one command to a SELECT.
To start with, create two tables
CREATE TABLE Lefty (ID int PRIMARY KEY)
CREATE TABLE Righty (ID int PRIMARY KEY)
INSERT INTO Lefty (ID) VALUES (1)
INSERT INTO Righty (ID) VALUES (2)
Then open two windows in SSMS. In the first put this code (don't run it yet)
BEGIN TRAN
UPDATE Lefty SET ID = 5
SELECT * FROM Righty
COMMIT TRAN
In the second window put in this code (also don't run it yet).
BEGIN TRAN
UPDATE Righty SET ID = 5
UPDATE Lefty SET ID = 5
COMMIT TRAN
Now, in the first window, run the first two commands (BEGIN TRAN
AND UPDATE LEFTY
).
That starts.
In the second window, run the whole transaction. It sits there waiting for your first window, and will wait forever.
In the first window, go back and run the SELECT * FROM Righty
and COMMIT TRAN
. 5, 4, 3, 2, 1 Boom deadlock - because the second window already had a lock on the table and therefore the SELECT in the first window couldn't run (and the second window couldn't run because the first had a lock on a table it needed).
(I'd like to reiterate - this is Brent Ozar's demo not mine! I'm just passing it on. Indeed, I recommend them).