Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 17ffda4

Browse files
Aversion to versions
Bigtime WIP, starting queries
1 parent 68a8afa commit 17ffda4

File tree

1 file changed

+297
-0
lines changed

1 file changed

+297
-0
lines changed

‎sp_BlitzLock.sql‎

Lines changed: 297 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,297 @@
1+
IF OBJECT_ID('dbo.sp_BlitzLock') IS NULL
2+
EXEC ('CREATE PROCEDURE dbo.sp_BlitzLock AS RETURN 0;');
3+
GO
4+
5+
ALTER PROCEDURE dbo.sp_BlitzLock
6+
(
7+
@Top INT = 2147483647, @StartDate DATETIME = '19000101', @EndDate DATETIME = '99991231', @Debug BIT = 0, @EventSessionPath NVARCHAR(256) = NULL, @Help BIT = 0
8+
)
9+
AS
10+
BEGIN
11+
12+
IF @Help = 1 PRINT '
13+
/*
14+
sp_BlitzLock from http://FirstResponderKit.org
15+
16+
This script checks for and analyzes deadlocks from the system health session or a custom extended event path
17+
18+
To learn more, visit http://FirstResponderKit.org where you can download new
19+
versions for free, watch training videos on how it works, get more info on
20+
the findings, contribute your own code, and more.
21+
22+
Unknown limitations of this version:
23+
- None. (If we knew them, they would be known. Duh.)
24+
25+
Changes - for the full list of improvements and fixes in this version, see:
26+
https://github.com/BrentOzarULTD/SQL-Server-First-Responder-Kit/
27+
28+
29+
Parameter explanations:
30+
HOLD YOUR HORSES
31+
32+
MIT License
33+
34+
Copyright for portions of sp_Blitz are held by Microsoft as part of project
35+
tigertoolbox and are provided under the MIT license:
36+
https://github.com/Microsoft/tigertoolbox
37+
38+
All other copyright for sp_BlitzLock are held by Brent Ozar Unlimited, 2017.
39+
40+
Copyright (c) 2017 Brent Ozar Unlimited
41+
42+
Permission is hereby granted, free of charge, to any person obtaining a copy
43+
of this software and associated documentation files (the "Software"), to deal
44+
in the Software without restriction, including without limitation the rights
45+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
46+
copies of the Software, and to permit persons to whom the Software is
47+
furnished to do so, subject to the following conditions:
48+
49+
The above copyright notice and this permission notice shall be included in all
50+
copies or substantial portions of the Software.
51+
52+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
53+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
54+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
55+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
56+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
57+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
58+
SOFTWARE.
59+
60+
*/';
61+
62+
63+
DECLARE @ProductVersion NVARCHAR(128);
64+
DECLARE @ProductVersionMajor FLOAT;
65+
DECLARE @ProductVersionMinor INT;
66+
67+
SET @ProductVersion = CAST(SERVERPROPERTY('ProductVersion') AS NVARCHAR(128));
68+
69+
SELECT @ProductVersionMajor = SUBSTRING(@ProductVersion, 1, CHARINDEX('.', @ProductVersion) + 1),
70+
@ProductVersionMinor = PARSENAME(CONVERT(VARCHAR(32), @ProductVersion), 2);
71+
72+
73+
IF @ProductVersionMajor < 11.0
74+
BEGIN
75+
RAISERROR(
76+
'sp_BlitzLock will throw a bunch of angry errors on versions of SQL Server earlier than 2012.',
77+
0,
78+
1) WITH NOWAIT;
79+
RETURN;
80+
END;
81+
82+
IF @Top IS NULL
83+
SET @Top = 2147483647
84+
85+
IF @StartDate IS NULL
86+
SET @StartDate = '19000101'
87+
88+
IF @EndDate IS NULL
89+
SET @EndDate = '99991231'
90+
91+
92+
IF OBJECT_ID('tempdb..#deadlock_data') IS NOT NULL
93+
DROP TABLE #deadlock_data;
94+
95+
IF OBJECT_ID('tempdb..#deadlock_process') IS NOT NULL
96+
DROP TABLE #deadlock_process;
97+
98+
IF OBJECT_ID('tempdb..#deadlock_stack') IS NOT NULL
99+
DROP TABLE #deadlock_stack;
100+
101+
IF OBJECT_ID('tempdb..#deadlock_resource') IS NOT NULL
102+
DROP TABLE #deadlock_resource;
103+
104+
IF OBJECT_ID('tempdb..#deadlock_owner_waiter') IS NOT NULL
105+
DROP TABLE #deadlock_owner_waiter;
106+
107+
IF OBJECT_ID('tempdb..#deadlock_findings') IS NOT NULL
108+
DROP TABLE #deadlock_findings;
109+
110+
CREATE TABLE #deadlock_findings
111+
(
112+
id INT IDENTITY(1, 1) PRIMARY KEY CLUSTERED,
113+
check_id INT NOT NULL,
114+
database_name NVARCHAR(256),
115+
object_name NVARCHAR(1000),
116+
finding NVARCHAR(4000),
117+
query_text XML
118+
);
119+
120+
121+
/*Grab the initial set of XML to parse*/
122+
WITH xml
123+
AS ( SELECT CONVERT(XML, event_data) AS deadlock_xml
124+
FROM sys.fn_xe_file_target_read_file('system_health*.xel', NULL, NULL, NULL) )
125+
SELECT TOP ( @Top ) xml.deadlock_xml
126+
INTO #deadlock_data
127+
FROM xml
128+
WHERE xml.deadlock_xml.value('(/event/@name)[1]', 'VARCHAR(255)') = 'xml_deadlock_report'
129+
AND xml.deadlock_xml.value('(/event/@timestamp)[1]', 'datetime') >= @StartDate
130+
AND xml.deadlock_xml.value('(/event/@timestamp)[1]', 'datetime') < @EndDate;
131+
132+
133+
134+
/*Parse process and input buffer XML*/
135+
SELECT dd.deadlock_xml.value('(event/@timestamp)[1]', 'DATETIME2') AS event_date,
136+
ca.dp.value('@id', 'NVARCHAR(256)') AS id,
137+
ca.dp.value('@currentdb', 'BIGINT') AS database_id,
138+
ca.dp.value('@logused', 'BIGINT') AS log_used,
139+
ca.dp.value('@waitresource', 'NVARCHAR(256)') AS wait_resource,
140+
ca.dp.value('@waittime', 'BIGINT') AS wait_time,
141+
ca.dp.value('@transactionname', 'NVARCHAR(256)') AS transaction_name,
142+
ca.dp.value('@lasttranstarted', 'DATETIME2(7)') AS last_tran_started,
143+
ca.dp.value('@lastbatchstarted', 'DATETIME2(7)') AS last_batch_started,
144+
ca.dp.value('@lastbatchcompleted', 'DATETIME2(7)') AS last_batch_completed,
145+
ca.dp.value('@lockMode', 'NVARCHAR(256)') AS lock_mode,
146+
ca.dp.value('@trancount', 'BIGINT') AS transaction_count,
147+
ca.dp.value('@clientapp', 'NVARCHAR(256)') AS client_app,
148+
ca.dp.value('@hostname', 'NVARCHAR(256)') AS host_name,
149+
ca.dp.value('@loginname', 'NVARCHAR(256)') AS login_name,
150+
ca.dp.value('@isolationlevel', 'NVARCHAR(256)') AS isolation_level,
151+
ca2.ib.query('.') AS input_buffer,
152+
ca.dp.query('.') AS process_xml
153+
INTO #deadlock_process
154+
FROM #deadlock_data AS dd
155+
CROSS APPLY dd.deadlock_xml.nodes('//deadlock/process-list/process') AS ca(dp)
156+
CROSS APPLY dd.deadlock_xml.nodes('//deadlock/process-list/process/inputbuf') AS ca2(ib);
157+
158+
159+
/*Parse execution stack XML*/
160+
SELECT dp.id,
161+
ca.dp.value('@procname', 'NVARCHAR(256)') AS proc_name,
162+
ca.dp.value('@sqlhandle', 'NVARCHAR(128)') AS sql_handle
163+
INTO #deadlock_stack
164+
FROM #deadlock_process AS dp
165+
CROSS APPLY dp.process_xml.nodes('//executionStack/frame') AS ca(dp);
166+
167+
168+
/*Grab the full resource list*/
169+
SELECT ca.dp.query('.') AS resource_xml
170+
INTO #deadlock_resource
171+
FROM #deadlock_data AS dd
172+
CROSS APPLY dd.deadlock_xml.nodes('//deadlock/resource-list') AS ca(dp);
173+
174+
175+
/*This parses object locks*/
176+
SELECT ca.dr.value('@dbid', 'BIGINT') AS database_id,
177+
ca.dr.value('@objectname', 'NVARCHAR(256)') AS object_name,
178+
ca.dr.value('@mode', 'NVARCHAR(256)') AS lock_mode,
179+
w.l.value('@id', 'NVARCHAR(256)') AS waiter_id,
180+
w.l.value('@mode', 'NVARCHAR(256)') AS waiter_mode,
181+
o.l.value('@id', 'NVARCHAR(256)') AS owner_id,
182+
o.l.value('@mode', 'NVARCHAR(256)') AS owner_mode
183+
INTO #deadlock_owner_waiter
184+
FROM #deadlock_resource AS dr
185+
CROSS APPLY dr.resource_xml.nodes('//resource-list/objectlock') AS ca(dr)
186+
CROSS APPLY ca.dr.nodes('//waiter-list/waiter') AS w(l)
187+
CROSS APPLY ca.dr.nodes('//owner-list/owner') AS o(l);
188+
189+
190+
/*This parses page locks*/
191+
INSERT #deadlock_owner_waiter
192+
SELECT ca.dr.value('@dbid', 'BIGINT') AS database_id,
193+
ca.dr.value('@objectname', 'NVARCHAR(256)') AS object_name,
194+
ca.dr.value('@mode', 'NVARCHAR(256)') AS lock_mode,
195+
w.l.value('@id', 'NVARCHAR(256)') AS waiter_id,
196+
w.l.value('@mode', 'NVARCHAR(256)') AS waiter_mode,
197+
o.l.value('@id', 'NVARCHAR(256)') AS owner_id,
198+
o.l.value('@mode', 'NVARCHAR(256)') AS owner_mode
199+
FROM #deadlock_resource AS dr
200+
CROSS APPLY dr.resource_xml.nodes('//resource-list/pagelock') AS ca(dr)
201+
CROSS APPLY ca.dr.nodes('//waiter-list/waiter') AS w(l)
202+
CROSS APPLY ca.dr.nodes('//owner-list/owner') AS o(l);
203+
204+
205+
/*This parses key locks*/
206+
INSERT #deadlock_owner_waiter
207+
SELECT ca.dr.value('@dbid', 'BIGINT') AS database_id,
208+
ca.dr.value('@objectname', 'NVARCHAR(256)') AS object_name,
209+
ca.dr.value('@mode', 'NVARCHAR(256)') AS lock_mode,
210+
w.l.value('@id', 'NVARCHAR(256)') AS waiter_id,
211+
w.l.value('@mode', 'NVARCHAR(256)') AS waiter_mode,
212+
o.l.value('@id', 'NVARCHAR(256)') AS owner_id,
213+
o.l.value('@mode', 'NVARCHAR(256)') AS owner_mode
214+
FROM #deadlock_resource AS dr
215+
CROSS APPLY dr.resource_xml.nodes('//resource-list/keylock') AS ca(dr)
216+
CROSS APPLY ca.dr.nodes('//waiter-list/waiter') AS w(l)
217+
CROSS APPLY ca.dr.nodes('//owner-list/owner') AS o(l);
218+
219+
220+
/*This parses rid locks*/
221+
INSERT #deadlock_owner_waiter
222+
SELECT ca.dr.value('@dbid', 'BIGINT') AS database_id,
223+
ca.dr.value('@objectname', 'NVARCHAR(256)') AS object_name,
224+
ca.dr.value('@mode', 'NVARCHAR(256)') AS lock_mode,
225+
w.l.value('@id', 'NVARCHAR(256)') AS waiter_id,
226+
w.l.value('@mode', 'NVARCHAR(256)') AS waiter_mode,
227+
o.l.value('@id', 'NVARCHAR(256)') AS owner_id,
228+
o.l.value('@mode', 'NVARCHAR(256)') AS owner_mode
229+
FROM #deadlock_resource AS dr
230+
CROSS APPLY dr.resource_xml.nodes('//resource-list/ridlock') AS ca(dr)
231+
CROSS APPLY ca.dr.nodes('//waiter-list/waiter') AS w(l)
232+
CROSS APPLY ca.dr.nodes('//owner-list/owner') AS o(l);
233+
234+
235+
/*Begin checks based on parsed values*/
236+
237+
/*Check 1 is deadlocks by database*/
238+
INSERT #deadlock_findings ( check_id, database_name, object_name, finding, query_text )
239+
SELECT 1 AS check_id,
240+
DB_NAME(dow.database_id) AS database_name,
241+
NULL AS object_name,
242+
'This database had '
243+
+ CONVERT(NVARCHAR(20), COUNT_BIG(DISTINCT dow.owner_id))
244+
+ ' deadlocks.',
245+
NULL AS query_text
246+
FROM #deadlock_owner_waiter AS dow
247+
GROUP BY DB_NAME(dow.database_id)
248+
249+
/*Check 2 is deadlocks by object*/
250+
251+
INSERT #deadlock_findings ( check_id, database_name, object_name, finding, query_text )
252+
SELECT 2 AS check_id,
253+
DB_NAME(dow.database_id) AS database_name,
254+
dow.object_name AS object_name,
255+
'This object had '
256+
+ CONVERT(NVARCHAR(20), COUNT_BIG(DISTINCT dow.owner_id))
257+
+ ' deadlocks.',
258+
NULL AS query_text
259+
FROM #deadlock_owner_waiter AS dow
260+
GROUP BY DB_NAME(dow.database_id), dow.object_name
261+
262+
263+
264+
SELECT df.id, df.check_id, df.database_name, df.object_name, df.finding, df.query_text
265+
FROM #deadlock_findings AS df
266+
ORDER BY df.check_id
267+
268+
IF @Debug = 1
269+
BEGIN
270+
271+
SELECT '#deadlock_data' AS table_name, *
272+
FROM #deadlock_data AS dd;
273+
274+
SELECT '#deadlock_owner_waiter' AS table_name, *
275+
FROM #deadlock_owner_waiter AS dow;
276+
277+
SELECT '#deadlock_process' AS table_name, *
278+
FROM #deadlock_process AS dp;
279+
280+
SELECT '#deadlock_resource' AS table_name, *
281+
FROM #deadlock_resource AS dr;
282+
283+
SELECT '#deadlock_stack' AS table_name, *
284+
FROM #deadlock_stack AS ds;
285+
END; -- End debug
286+
287+
END; --Final End
288+
GO
289+
290+
EXEC dbo.sp_BlitzLock @Debug = 1;
291+
292+
293+
294+
295+
296+
297+

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /