SQL query to get the deadlocks in SQL SERVER 2008 [duplicate] - sql

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Help with deadlock in Sql Server 2008
SQLServer automatically logs all deadlocks. Can anyone help me to get sql query which will capture deadlocks data that is being collected, for a recent event.
I am using SQL SERVER 2008 R2 for my development activities.
Thanks & Regards,
Santosh Kumar Patro

You can use a deadlock graph and gather the information you require from the log file.
The only other way I could suggest is digging through the information by using EXEC SP_LOCK (Soon to be deprecated), EXEC SP_WHO2 or the sys.dm_tran_locks table.
SELECT L.request_session_id AS SPID,
DB_NAME(L.resource_database_id) AS DatabaseName,
O.Name AS LockedObjectName,
P.object_id AS LockedObjectId,
L.resource_type AS LockedResource,
L.request_mode AS LockType,
ST.text AS SqlStatementText,
ES.login_name AS LoginName,
ES.host_name AS HostName,
TST.is_user_transaction as IsUserTransaction,
AT.name as TransactionName,
CN.auth_scheme as AuthenticationMethod
FROM sys.dm_tran_locks L
JOIN sys.partitions P ON P.hobt_id = L.resource_associated_entity_id
JOIN sys.objects O ON O.object_id = P.object_id
JOIN sys.dm_exec_sessions ES ON ES.session_id = L.request_session_id
JOIN sys.dm_tran_session_transactions TST ON ES.session_id = TST.session_id
JOIN sys.dm_tran_active_transactions AT ON TST.transaction_id = AT.transaction_id
JOIN sys.dm_exec_connections CN ON CN.session_id = ES.session_id
CROSS APPLY sys.dm_exec_sql_text(CN.most_recent_sql_handle) AS ST
WHERE resource_database_id = db_id()
ORDER BY L.request_session_id
http://www.sqlmag.com/article/sql-server-profiler/gathering-deadlock-information-with-deadlock-graph
http://weblogs.sqlteam.com/mladenp/archive/2008/04/29/SQL-Server-2005-Get-full-information-about-transaction-locks.aspx

In order to capture deadlock graphs without using a trace (you don't need profiler necessarily), you can enable trace flag 1222. This will write deadlock information to the error log. However, the error log is textual, so you won't get nice deadlock graph pictures - you'll have to read the text of the deadlocks to figure it out.
I would set this as a startup trace flag (in which case you'll need to restart the service). However, you can run it only for the current running instance of the service (which won't require a restart, but which won't resume upon the next restart) using the following global trace flag command:
DBCC TRACEON(1222, -1);
A quick search yielded this tutorial:
Finding SQL Server Deadlocks Using Trace Flag 1222
Also note that if your system experiences a lot of deadlocks, this can really hammer your error log, and can become quite a lot of noise, drowning out other, important errors.
Have you considered third party monitoring tools? SQL Sentry and Plan Explorer, for example, have a much nicer deadlock graph, showing you object / index names, as well as the order in which the locks were taken. As a bonus, these are captured for you automatically on monitored servers without having to configure trace flags, run your own traces, etc.:
New Deadlock Visualizations in SQL Sentry and Plan Explorer
Analyzing Deadlocks in SQL Sentry
Disclaimer: I used to work for SQL Sentry.

Related

Basic select deadlocks itself

So, I have been looking into more SQL server management tools using a few of them, and I have been amazed to find simple selects blocking themselves and causing deadlocks. I have done a little research, but I am truly amazed this could happen. Can anyone clarify, or maybe solve, why this happens?
I'm talking about a simple select.
SELECT
ID
FROM
MainTable
WHERE
Name Like 'John Smith'
Using Microsoft SQL Server Managment Studios, if it matters.
In SQL 2000 processes would sometimes report as blocking themselves, but I don't think this applies in later versions of SQL Server.
latch waits reported as blocking
It is definitely possible for a SELECT statement to cause a deadlock, because shared locks are acquired when data is selected, but there would also have to be another process that is trying to update the data.
A parallel execution plan can show as a SPID blocking itself. This is basically just threads waiting for the other tasks in the query to complete. Deadlocking is another matter, caused by different sessions waiting on each other. Deadlocks (and excessive parallelism) can be a symptom of the need for query and index tuning.
If you are running SQL 2008 or later, deadlock information is captured by the system_helath extended event trace by default. Below is a query to extract recent deadlock information from the ring buffer. This will eliminate some of the guesswork.
SELECT
xed.value('#timestamp', 'datetime') as Creation_Date,
xed.query('.') AS Extend_Event
FROM
(
SELECT CAST([target_data] AS XML) AS Target_Data
FROM sys.dm_xe_session_targets AS xt
INNER JOIN sys.dm_xe_sessions AS xs
ON xs.address = xt.event_session_address
WHERE xs.name = N'system_health'
AND xt.target_name = N'ring_buffer'
) AS XML_Data
CROSS APPLY Target_Data.nodes('RingBufferTarget/event[#name="xml_deadlock_report"]') AS XEventData(xed)
ORDER BY Creation_Date DESC;
This simple select cannot deadlock itself, the only possible cause is something else is updating/deleting rows while you are reading.
Try launching SQL Server Profiler and use the:
deadlock
deadlock chain
deadloch graph
events in your template.
The Deadlock graph in particular will help you identify which two processes are causing trhe deadlock and the one chosen as deadlock victim

SQL Server function intermittent performance issues

We have a function in our database that searches two large tables to see if a value exists. It is a pretty large query, but it is optimized to use indexes and generally runs pretty fast.
Three times over the past 2 weeks, this function decided to go haywire and run extremely slow, which causes deadlocking and bad performance all around. This happens even at times of less than peak usage.
Rebuilding the function using "Alter Function" in SQL Server seems to take care of the issue. Once we do that, the server usage goes back to normal and everything is OK.
This leads us to think that the functions query plan has rebuilt, and is taking the correct indexes into account, but we have no idea why SQL Server decided to change the query plan to a worse plan all of a sudden.
Does anyone have any ideas what might cause this behavior, or how to test for it, or prevent it? We are running SQL Server 2008 Enterprise.
The behaviour you are describing is often due to an incorrectly cached query plan and/or out of date statistics.
It commonly occurs when you have a large number of parameters in a WHERE clause, especially a long list of those that are of the form:
(#parameter1 is NULL OR TableColumn1 = #parameter1)
Say, the cached query plan expires, and the proc is called with an unrepresentative set of parameters. The plan is then cached for this data profile. BUT, if the proc is more oftenly common with a very different set of parameters, the plan might not be appropriate. This is often known as 'parameter sniffing'.
There are ways to mitigate and eliminate this problem but they may involve trade-offs and depend on your SQL Server version. Look at OPTIMIZE FOR and OPTIMIZE FOR UNKNOWN. IF (and it's a big if) the proc is called infrequently but must run as fast as possible you can mark it as OPTION(RECOMPILE), to force a recompile each time it is called, BUT don't do this for frequently called procs OR without investigation.
[NOTE: be aware of which Service pack and Cumulative Update (CU) your SQL Server 2008 box has, as the recompile and parameter sniffing logic works differently in some versions]
Run this query (from Glenn Berry) to determine the state of statistics:
-- When were Statistics last updated on all indexes?
SELECT o.name, i.name AS [Index Name],
STATS_DATE(i.[object_id], i.index_id) AS [Statistics Date],
s.auto_created, s.no_recompute, s.user_created, st.row_count
FROM sys.objects AS o WITH (NOLOCK)
INNER JOIN sys.indexes AS i WITH (NOLOCK)
ON o.[object_id] = i.[object_id]
INNER JOIN sys.stats AS s WITH (NOLOCK)
ON i.[object_id] = s.[object_id]
AND i.index_id = s.stats_id
INNER JOIN sys.dm_db_partition_stats AS st WITH (NOLOCK)
ON o.[object_id] = st.[object_id]
AND i.[index_id] = st.[index_id]
WHERE o.[type] = 'U'
ORDER BY STATS_DATE(i.[object_id], i.index_id) ASC OPTION (RECOMPILE);

Tips for tracking down mystery update SQL?

I just started a new job and was given a bug to track down and fix. The basic issues it that a field in a DB record is being cleared out and no one knows why. So far I have tried:
Checking the table for triggers,
there are none.
Monitoring the table using SQL
Server profiler for the last couple
of days in the hopes that the error
would happen again but unfortunately
it hasn't.
Reviewing all the code that does
inserts/updates and I didn't see
anything that would cause this
problem.
Does anyone have any other suggests for finding what could have updated this record? Am I not checking something that I should be? Are there any other sources of information that I should look at?
Create a trigger that will write to a history table. Include columns for the date of the write as well as the user.
::fn_dblog() will show you at the very least when the update occurred (as sequence, not as time) and what other operations were done by that transaction. From the information on what other operations this transaction did, along with what other transactions were doing at that moment, you should be able to narrow down at least the context under which the update occurred, from which point code inspection is a viable option to continue.
Reading the log requires ... the log so your database should be in full recovery mode.
select
schema_name = s.name,
object_name = o.name
from sys.sql_modules m join sys.objects o on m.object_id = o.object_id
join sys.schemas s on o.schema_id = s.schema_id
where definition like '%FieldName%'
This query looks through all the objects in the database (stored procedures, functions, views) and looks for any place where 'FieldName' is being refered. I would go through all the objects returned by this query to see if anything unusual is being done with the Field. This might be extremely tedious as it might return more results than you care about, but its a sure shot way of catching all the references to the field
If you are on SQL Server 2008 you can use extended events to get the full stack trace for the offending statement. Example code here Create Trigger to log SQL that affected table?

SQl statement to monitor SQL Server Locks

Which SQL sentence (function or stored procedure) I can use to monitor an SQL Server DeadLock, caused by an UPDATE statement?
try this query to see blocking processes, including the actual SQL query text:
SELECT
r.session_id AS spid
,r.cpu_time,r.reads,r.writes,r.logical_reads
,r.blocking_session_id AS BlockingSPID
,LEFT(OBJECT_NAME(st.objectid, st.dbid),50) AS ShortObjectName
,LEFT(DB_NAME(r.database_id),50) AS DatabaseName
,s.program_name
,s.login_name
,OBJECT_NAME(st.objectid, st.dbid) AS ObjectName
,SUBSTRING(st.text, (r.statement_start_offset/2)+1,( (CASE r.statement_end_offset
WHEN -1 THEN DATALENGTH(st.text)
ELSE r.statement_end_offset
END - r.statement_start_offset
)/2
) + 1
) AS SQLText
FROM sys.dm_exec_requests r
JOIN sys.dm_exec_sessions s ON r.session_id = s.session_id
CROSS APPLY sys.dm_exec_sql_text (sql_handle) st
--WHERE r.session_id!=##SPID --uncomment to not see this query
deadlocks are easily trapped with the profiler:
Try running the run a trace in the profiler (pick the blank template), select the "deadlock graph event", and on the new tab that appears (Events Extraction Settings), save each (check "save deadlock XML events separately") in its own file. Open this file in an xml viewer and it will be easy to tell what is happening. Each process is contained, with an execution stack of procedure/trigger/etc calls, etc. and all locks are in there too.
Look at the "resource list" section of the file, it will show what is being locked and held by each process causing the deadlock. Figure out how to not have one of these locked and the deadlock will be resolved.
Let this trace run until the deadlock happens again, info is only recorded when a deadlock happens, so there isn't much overhead. If it never happens again, good it is solved, if not you have captured all the info.
I think you're better placed to use SQL Profiler to monitor deadlocks - see here. SQL Profiler shows the deadlocks in a diagram to make it easier to determine what caused them.
SELECT * FROM sys.dm_exec_requests WHERE blocking_session_id <> 0
But that will show you requests that are blocking, which is normal for SQL Server and doesn't indicate a deadlock. If SQL Server detects a deadlock it will kill one of the processes to allow the others to continue. So you can't use a function or stored procedure to monitor this as by the time it happens it has already finished.
You can either use the SQL Profiler or Trace Flags

Finding out which locks that are acquired in a query on SQL Server?

I have a SQL statement from my application. I'd like to know which locks that statement acquires; how can I do that with SQL server?
The statement has been involved in a deadlock, which I'm trying to analyze; I cannot reproduce the deadlock.
I'm running on MS SQL Server 2005.
You can run the statement in a transaction, but not commit the transaction. Since the locks will be held until the transaction is committed, this gives you time to inspect the locks. (Not indefinitely, but like 5 minutes by default.)
Like:
BEGIN TRANSACTION
select * from table
Then open Management Studio and check the locks. They're in Management -> Activity Monitor -> Locks by Object or Locks by Process. After you're done, run:
COMMIT TRANSACTION
to free the locks.
I would suggest that you turn on the Deadlock Detection Trace Flags in the first instance, rather than running a Profiler Trace indefinitely.
This way, the event details will be logged to the SQL Server Error Log.
Review the following Books Online reference for details of the various trace flags. You need to use 1204 and/or 1222
http://msdn.microsoft.com/en-us/library/ms188396(SQL.90).aspx
Be sure to enable the trace flags with server scope and not just the current session. For example use:
DBCC TRACEON(1222,-1)
Here's a query that will show you all active locks, who's got them, and what object they are on. I pulled this from a technet article or something years and years ago. It works on SQL 2000 and 2005 (change sysobjects to sys.objects for 2005.) Uncomment the WHERE clause if you want to restrict it to just this databse, and just the "EXCLUSIVE" locks.
select 'Locks' as Locks,
spid, nt_username, name, hostname, loginame, waittime, open_tran,
convert(varchar ,getdate() - last_batch, 114) as TimeSinceLastCommand,
case req_mode
when 0 then 'Not granted'
when 1 then 'Schema stability'
when 2 then 'Schema modification'
when 3 then 'Intent shared'
when 4 then 'Shared intent update'
when 5 then 'Intent shared shared'
when 6 then 'Intent exclusive'
when 7 then 'Shared Intent Exclusive'
when 8 then 'Shared'
when 9 then 'Update'
when 10 then 'Intent insert NULL'
when 11 then 'Intent shared exclusive'
when 12 then 'Intent update'
when 13 then 'Intent shared-update'
when 14 then 'Exclusive'
when 15 then 'Bulk operation'
else str(req_mode) end as LockMode
from master..syslockinfo
left join sysobjects so on so.id = rsc_objid
left join master..sysprocesses sp on sp.spid = req_spid
--where rsc_dbid = (select db_id()) and ltrim(req_mode) in (6,7,11,14)
run a trace in the profiler (pick the blank template), select the deadlock graph event, and on the new tab that appears (Events Extraction Settings), save each (check save deadlock XML events separately) in its own file. Open this file in an xml viewer and it will be easy to tell what is happening. Each process is contained, with a stack of procedure calls, etc. and all locks are in there too.
Let this trace run until the deadlock happens again, info is only recorded when a deadlock happens, so not much overhead. If it never happens again, good it is solved, if not you have captured all the info.
You can run a profiler trace on your dev box for the queries and see exactly what locks are taken. This is typically a huge amount of data, but much of it will be patterns you can skim over. E.g. for read committed isolation, you will see a succession of locks being acquired and released as you do a table or index scan (each row must be locked before it is read, and it is immediately released after it is read).
What isolation do you run under? What kind of queries are deadlocking? Are you using explicit transactions that encompass multiple updates, or are they single statements deadlocking?
The most typical case for a deadlock is a transaction with the sequence (update table x, update table y), and a second transaction with the sequence (update table y, update table x). The common solution is to make sure you use the same update sequence across queries.
Let us know what kind of queries they are, there are different common issues for different types of transactions.
Troubleshooting deadlocks:
http://blogs.msdn.com/bartd/archive/2006/09/09/747119.aspx
http://blogs.msdn.com/bartd/archive/2006/09/13/751343.aspx
Reproducing deadlocks:
http://sqlblog.com/blogs/alexander_kuznetsov/archive/2009/01/01/reproducing-deadlocks-involving-only-one-table.aspx