May 19, 2005 at 6:05 am
I have this very strange situation where I am getting deadlocks when I try and read from the database.
i.e. so the process being killed is something simple like "select blah blah blah from BlahTable where id = @k"
Now I wouldn't have thought that this would would try an obtain a lock that could cause a deadlock.
There are a lot of users on the system so it is very difficult to know what the successfull process was doing at the time of deadlock but I'm wondering if there is something wrong with the databse that this is happening.
Any thoughts appreciated.
May 20, 2005 at 1:55 am
try BOL, search for "deadlocks, troubleshooting". This may help to trace where the deadlock is occuring.
HTH Andy
May 20, 2005 at 5:06 am
At least on SQL 7.0, not sure about 2000 or 2005, you can go to managment, current activity, locks / process ID and see who was locking and if you double click the one that it says is blocking you can see the SQL that it is processing. You can also kill that process from there.
Hope that helps.
May 20, 2005 at 7:18 am
Hello Dale,
This is something that also happened to us: Having a simple "firehose" cursor involved in a deadlock (doing nothing else on the connection and not being in a transaction).
When it happened to us (about 2 years ago) I could not understand why.
But after having read the Kalen Delaney document "Hands-On SQL Server 2000 Troubleshooting : Locking and blocking" from NetImpress, it becomes clearer.
I strongly suggest you to read it.
N.B. In SQL Server 2005 if you use "Row Versionning" with "Read commited" or "Snapshot" isolation level there will be no more read locks... thus no more deadlock possible on reading data.
Best regards,
Carl
May 20, 2005 at 10:19 am
Dale,
You likely have another process (or two) that is performing an insert, update, or delete on the resources of the data you are requesting. sp_who2 is a helpful system stored proc to identify the locking process.
Here is a script that expands on sp_who2 to also display the last batch each process last executed:
/******************************************************
** Expansion on sp_who2 to also display the
** last batch each process executed for the
** requested database
******************************************************/
USE master
DECLARE @SPID int,
@dbname varchar(255)
SET @dbname = 'database' /* database name */
CREATE TABLE #status (
SPID int,
Status varchar(255),
Login varchar(255),
HostName varchar(255),
BlkBy varchar(20),
DBName varchar(255),
Command varchar(255),
CPUTime int,
DiskIO int,
LastBatch varchar(255),
ProgramName varchar(255),
SPID1 int
)
INSERT INTO #status
EXEC sp_who2
ALTER TABLE #status ADD LastBatchStatement varchar(255)
CREATE TABLE #inputbuffer (
EventType varchar(30),
Parameters int,
EventInfo varchar(255)
)
SET @SPID = 0
WHILE EXISTS (
SELECT TOP 1 SPID
FROM #status
WHERE SPID > @SPID
AND Login <> 'sa'
AND DBName = @dbname
)
BEGIN
SELECT @SPID = MIN(SPID)
FROM #status
WHERE SPID > @SPID
AND Login <> 'sa'
AND DBName = @dbname
INSERT INTO #inputbuffer
EXEC('DBCC INPUTBUFFER(' + @SPID + ')')
UPDATE s
SET LastBatchStatement = ib.EventInfo
FROM #status s,
#inputbuffer ib
WHERE s.SPID = @SPID
TRUNCATE TABLE #inputbuffer
END
SELECT *
FROM #status
WHERE Login <> 'sa'
AND DBName = @dbname
DROP TABLE #status
DROP TABLE #inputbuffer
GO
The following script may be useful in identifying specific resources being locked:
/******************************************************
** Returns the locks occuring in a database
** (including indexes)
******************************************************/
USE master
DECLARE @dbid int
SET @dbid = 0 /* dbid in master.dbo.sysdatabases for the database */
CREATE TABLE #lock (
spid int,
dbid int,
ObjId int,
IndId int,
Type varchar(20),
Resource varchar(255),
Mode varchar(20),
Status varchar(255)
)
INSERT INTO #lock
EXEC sp_lock
SELECT *
FROM #lock
WHERE dbid = @dbid
DROP TABLE #lock
GO
I hope these scripts are helpful to you in troubleshooting. Enjoy...
May 31, 2005 at 4:26 am
Thanks for all the responses:
try BOL, search for "deadlocks, troubleshooting". This may help to trace where the deadlock is occuring.
Having read everything I could find regarding deadlocks in the BOL I could still not see how this could occur.
At least on SQL 7.0, not sure about 2000 or 2005, you can go to managment, current activity, locks / process ID and see who was locking and if you double click the one that it says is blocking you can see the SQL that it is processing. You can also kill that process from there.
This is an extremely busy system with many users, deadlocks only happen when it is fairly busy so not really possible to look at the current locks.
You likely have another process (or two) that is performing an insert, update, or delete on the resources of the data you are requesting. sp_who2 is a helpful system stored proc to identify the locking process.
I am fairly certain that no insert, update, or delete is happening on the row in question, therefore I think that there must be a table lock happening?
Given what I was saying above about how busy the system is, and that I am only notified about a deadlock after the event is there any way I can use sp_who2 to determine what is happening?
But after having read the Kalen Delaney document "Hands-On SQL Server 2000 Troubleshooting : Locking and blocking" from NetImpress, it becomes clearer.
That sounds great.
May 31, 2005 at 4:52 am
But after having read the Kalen Delaney document "Hands-On SQL Server 2000 Troubleshooting : Locking and blocking" from NetImpress, it becomes clearer.
Except that Amazon will not allow this book to be sold to people in the UK
June 1, 2005 at 5:15 am
Hi Carl,
Thanks for the info, I managed to get hold of a copy of the book and read it this morning.
Can you say a bit more about what was causing the problem in your case?
It is something to do with the combination of cursors and triggers that is causing us the problems - but its proving difficult to track down.
Dale
June 1, 2005 at 6:24 am
Hi Dale,
To be honest when this situation arise we were having a lot of other troubles involving LOCKs, DEADLOCKs, application bugs, ... it was in the summer of 2002.
We were never able to reproduce this particular situation at will.
All I remember is that, having only a "firehose" cursor, The application was invloved in (choosen as the victim of) deadlock. So we modified the application to retry the read or the transaction if we were in it.
The first time I read the document (twice), I identified 2 or 3 possible situations but I don't remember exactly which ones.
I should read it again.
Best regards,
Carl
June 3, 2005 at 7:35 am
I investigated the query further that was getting killed by the deadlock, and this query only uses the following locks:
S
IS
Sch-S
Now I thought that a deadlock occured when 2 proceses end up waiting on each other (directly or indirectly), but I cannot understand how a process that has only S, IS & Sch-S locks could even participate in a deadlock?
For example if someone else was updating the table then this process might get blocked, but I cannot see how it would ever get deadlocked?
Any ideas?
June 3, 2005 at 9:28 am
What isolation level is it running in?
Here is an example to deadlock a reading-only process.
-- Run this in first query anylyzer window:
BEGIN TRAN
UPDATE sometable SET something = whatever
-- Now open a second window and run this:
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ
BEGIN TRAN
SELECT * FROM othertable
-- Back in the first window now run this:
UPDATE othertable SET somethingelse = whatever
-- In the second window, run this, which will produce a deadlock:
SELECT * FROM sometable
June 3, 2005 at 9:38 am
Also, maybe lock escalation is involved... not sure.
Carl
June 3, 2005 at 9:41 am
What's that??
June 3, 2005 at 9:43 am
Thanks Chris... that is very helpful... Now I know they are possible
I still can't see how I would be getting that situation, because I don't use transactions on the reads, let alone transactions using ISOLATION LEVEL REPEATABLE READ
In fact the only thing I am doing is sub-queries within the main query
i.e. select x, (select y from table2) from table1
So I do wonder what the implicit transactions look like when using a sub-query such as this - would it be using an implicit transaction with REPEATABLE READ?
Unless ADO sets the level to REPEATABLE READ - hmmm something to investigate.
Thanks again,
June 3, 2005 at 9:45 am
From BOL:
Lock escalation is the process of converting many fine-grain locks into fewer coarse-grain locks, reducing system overhead. Microsoft® SQL Server™ 2000 automatically escalates row locks and page locks into table locks when a transaction exceeds its escalation threshold.
For example, when a transaction requests rows from a table, SQL Server automatically acquires locks on those rows affected and places higher-level intent locks on the pages and table, or index, which contain those rows. When the number of locks held by the transaction exceeds its threshold, SQL Server attempts to change the intent lock on the table to a stronger lock (for example, an intent exclusive (IX) would change to an exclusive (X) lock). After acquiring the stronger lock, all page and row level locks held by the transaction on the table are released, reducing lock overhead.
SQL Server may choose to do both row and page locking for the same query, for example, placing page locks on the index (if enough contiguous keys in a nonclustered index node are selected to satisfy the query) and row locks on the data. This reduces the likelihood that lock escalation will be necessary.
Lock escalation thresholds are determined dynamically by SQL Server and do not require configuration.
Best regards,
Carl
Viewing 15 posts - 1 through 15 (of 29 total)
You must be logged in to reply to this topic. Login to reply