|
4 | 4 |
|
5 | 5 | ALTER PROCEDURE dbo.sp_BlitzLock
|
6 | 6 | (
|
7 | | - @Top INT = 2147483647, @StartDate DATETIME = '19000101', @EndDate DATETIME = '99991231', @Debug BIT = 0, @EventSessionPath NVARCHAR(256) = NULL, @Help BIT = 0 |
| 7 | + @Top INT = 2147483647, |
| 8 | + @StartDate DATETIME = '19000101', |
| 9 | + @EndDate DATETIME = '99991231', |
| 10 | + @Debug BIT = 0, |
| 11 | + @EventSessionPath NVARCHAR(256) = NULL, |
| 12 | + @Help BIT = 0, |
| 13 | + @VersionDate DATETIME = NULL OUTPUT |
8 | 14 | )
|
9 | 15 | AS
|
| 16 | +SET NOCOUNT ON; |
| 17 | +SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; |
| 18 | +DECLARE @Version VARCHAR(30); |
| 19 | +SET @Version = '1.0'; |
| 20 | +SET @VersionDate = '20171201'; |
| 21 | + |
| 22 | + |
| 23 | + |
10 | 24 | BEGIN
|
11 | 25 |
|
12 | 26 | IF @Help = 1 PRINT '
|
|
15 | 29 |
|
16 | 30 | This script checks for and analyzes deadlocks from the system health session or a custom extended event path
|
17 | 31 |
|
| 32 | + Variables you can use: |
| 33 | + @Top: Use if you want to limit the number of deadlocks to return. |
| 34 | + This is ordered by event date ascending |
| 35 | + |
| 36 | + @DatabaseName: If you want to filter to a specific database |
| 37 | + |
| 38 | + @StartDate: The date you want to start searching on. |
| 39 | + |
| 40 | + @EndDate: The date you want to stop searching on. |
| 41 | + |
| 42 | + @ObjectName: If you want to filter to a specific able. |
| 43 | + The object name has to be fully qualified ''Database.Schema.Table'' |
| 44 | + |
| 45 | + @StoredProcName: If you want to search for a single stored proc |
| 46 | + |
| 47 | + @AppName: If you want to filter to a specific application |
| 48 | + |
| 49 | + @HostName: If you want to filter to a specific host |
| 50 | + |
| 51 | + @LoginName: If you want to filter to a specific login |
| 52 | + |
| 53 | + @EventSessionPath: If you want to point this at an XE session rather than the system health session. |
| 54 | + |
| 55 | + |
| 56 | + |
18 | 57 | To learn more, visit http://FirstResponderKit.org where you can download new
|
19 | 58 | versions for free, watch training videos on how it works, get more info on
|
20 | 59 | the findings, contribute your own code, and more.
|
|
124 | 163 | FROM xml
|
125 | 164 | WHERE xml.deadlock_xml.value('(/event/@name)[1]', 'VARCHAR(255)') = 'xml_deadlock_report'
|
126 | 165 | AND xml.deadlock_xml.value('(/event/@timestamp)[1]', 'datetime') >= @StartDate
|
127 | | - AND xml.deadlock_xml.value('(/event/@timestamp)[1]', 'datetime') < @EndDate; |
| 166 | + AND xml.deadlock_xml.value('(/event/@timestamp)[1]', 'datetime') < @EndDate |
| 167 | + ORDER BY xml.deadlock_xml.value('(/event/@timestamp)[1]', 'datetime') |
| 168 | + OPTION ( RECOMPILE ); |
128 | 169 |
|
129 | 170 | IF @@ROWCOUNT < 1
|
130 | 171 | BEGIN
|
|
161 | 202 | INTO #deadlock_process
|
162 | 203 | FROM #deadlock_data AS dd
|
163 | 204 | CROSS APPLY dd.deadlock_xml.nodes('//deadlock/process-list/process') AS ca(dp)
|
164 | | - CROSS APPLY dd.deadlock_xml.nodes('//deadlock/process-list/process/inputbuf') AS ca2(ib); |
| 205 | + CROSS APPLY dd.deadlock_xml.nodes('//deadlock/process-list/process/inputbuf') AS ca2(ib) |
| 206 | + OPTION ( RECOMPILE ); |
165 | 207 |
|
166 | 208 |
|
167 | 209 | /*Parse execution stack XML*/
|
|
170 | 212 | ca.dp.value('@sqlhandle', 'NVARCHAR(128)') AS sql_handle
|
171 | 213 | INTO #deadlock_stack
|
172 | 214 | FROM #deadlock_process AS dp
|
173 | | - CROSS APPLY dp.process_xml.nodes('//executionStack/frame') AS ca(dp); |
| 215 | + CROSS APPLY dp.process_xml.nodes('//executionStack/frame') AS ca(dp) |
| 216 | + OPTION ( RECOMPILE ); |
174 | 217 |
|
175 | 218 |
|
176 | 219 | /*Grab the full resource list*/
|
177 | 220 | SELECT ca.dp.query('.') AS resource_xml
|
178 | 221 | INTO #deadlock_resource
|
179 | 222 | FROM #deadlock_data AS dd
|
180 | | - CROSS APPLY dd.deadlock_xml.nodes('//deadlock/resource-list') AS ca(dp); |
| 223 | + CROSS APPLY dd.deadlock_xml.nodes('//deadlock/resource-list') AS ca(dp) |
| 224 | + OPTION ( RECOMPILE ); |
181 | 225 |
|
182 | 226 |
|
183 | 227 | /*This parses object locks*/
|
|
192 | 236 | FROM #deadlock_resource AS dr
|
193 | 237 | CROSS APPLY dr.resource_xml.nodes('//resource-list/objectlock') AS ca(dr)
|
194 | 238 | CROSS APPLY ca.dr.nodes('//waiter-list/waiter') AS w(l)
|
195 | | - CROSS APPLY ca.dr.nodes('//owner-list/owner') AS o(l); |
| 239 | + CROSS APPLY ca.dr.nodes('//owner-list/owner') AS o(l) |
| 240 | + OPTION ( RECOMPILE ); |
196 | 241 |
|
197 | 242 |
|
198 | 243 | /*This parses page locks*/
|
|
207 | 252 | FROM #deadlock_resource AS dr
|
208 | 253 | CROSS APPLY dr.resource_xml.nodes('//resource-list/pagelock') AS ca(dr)
|
209 | 254 | CROSS APPLY ca.dr.nodes('//waiter-list/waiter') AS w(l)
|
210 | | - CROSS APPLY ca.dr.nodes('//owner-list/owner') AS o(l); |
| 255 | + CROSS APPLY ca.dr.nodes('//owner-list/owner') AS o(l) |
| 256 | + OPTION ( RECOMPILE ); |
211 | 257 |
|
212 | 258 |
|
213 | 259 | /*This parses key locks*/
|
|
222 | 268 | FROM #deadlock_resource AS dr
|
223 | 269 | CROSS APPLY dr.resource_xml.nodes('//resource-list/keylock') AS ca(dr)
|
224 | 270 | CROSS APPLY ca.dr.nodes('//waiter-list/waiter') AS w(l)
|
225 | | - CROSS APPLY ca.dr.nodes('//owner-list/owner') AS o(l); |
| 271 | + CROSS APPLY ca.dr.nodes('//owner-list/owner') AS o(l) |
| 272 | + OPTION ( RECOMPILE ); |
226 | 273 |
|
227 | 274 |
|
228 | 275 | /*This parses rid locks*/
|
|
237 | 284 | FROM #deadlock_resource AS dr
|
238 | 285 | CROSS APPLY dr.resource_xml.nodes('//resource-list/ridlock') AS ca(dr)
|
239 | 286 | CROSS APPLY ca.dr.nodes('//waiter-list/waiter') AS w(l)
|
240 | | - CROSS APPLY ca.dr.nodes('//owner-list/owner') AS o(l); |
| 287 | + CROSS APPLY ca.dr.nodes('//owner-list/owner') AS o(l) |
| 288 | + OPTION ( RECOMPILE ); |
241 | 289 |
|
242 | 290 |
|
243 | 291 | /*Begin checks based on parsed values*/
|
|
253 | 301 | + ' deadlocks.',
|
254 | 302 | NULL AS query_text
|
255 | 303 | FROM #deadlock_owner_waiter AS dow
|
256 | | - GROUP BY DB_NAME(dow.database_id); |
| 304 | + GROUP BY DB_NAME(dow.database_id) |
| 305 | + OPTION ( RECOMPILE ); |
257 | 306 |
|
258 | 307 | /*Check 2 is deadlocks by object*/
|
259 | 308 |
|
|
267 | 316 | + ' deadlocks.',
|
268 | 317 | NULL AS query_text
|
269 | 318 | FROM #deadlock_owner_waiter AS dow
|
270 | | - GROUP BY DB_NAME(dow.database_id), dow.object_name; |
| 319 | + GROUP BY DB_NAME(dow.database_id), dow.object_name |
| 320 | + OPTION ( RECOMPILE ); |
271 | 321 |
|
272 | 322 |
|
273 | 323 | /*Check 3 looks for Serializable locking*/
|
|
283 | 333 | NULL AS query_text
|
284 | 334 | FROM #deadlock_process AS dp
|
285 | 335 | WHERE dp.isolation_level LIKE 'serializable%'
|
286 | | - GROUP BY DB_NAME(dp.database_id); |
| 336 | + GROUP BY DB_NAME(dp.database_id) |
| 337 | + OPTION ( RECOMPILE ); |
| 338 | + |
287 | 339 |
|
288 | 340 | /*Check 4 looks for Repeatable Read locking*/
|
289 | 341 | INSERT #deadlock_findings ( check_id, database_name, object_name, finding_group, finding, query_text )
|
|
298 | 350 | NULL AS query_text
|
299 | 351 | FROM #deadlock_process AS dp
|
300 | 352 | WHERE dp.isolation_level LIKE 'repeatable read%'
|
301 | | - GROUP BY DB_NAME(dp.database_id); |
| 353 | + GROUP BY DB_NAME(dp.database_id) |
| 354 | + OPTION ( RECOMPILE ); |
| 355 | + |
302 | 356 |
|
303 | 357 | /*Check 5 breaks down app, host, and login information*/
|
304 | 358 | INSERT #deadlock_findings ( check_id, database_name, object_name, finding_group, finding, query_text )
|
|
317 | 371 | AS finding,
|
318 | 372 | NULL AS query_text
|
319 | 373 | FROM #deadlock_process AS dp
|
320 | | - GROUP BY DB_NAME(dp.database_id), dp.login_name, dp.client_app, dp.host_name; |
| 374 | + GROUP BY DB_NAME(dp.database_id), dp.login_name, dp.client_app, dp.host_name |
| 375 | + OPTION ( RECOMPILE ); |
| 376 | + |
321 | 377 |
|
322 | 378 | /*Check 6 breaks down the types of locks (object, page, key, etc.)*/
|
323 | 379 | WITH lock_types AS (
|
|
343 | 399 | FOR XML PATH(N''), TYPE).value(N'.[1]', N'NVARCHAR(MAX)'), 1, 1, N'')
|
344 | 400 | + ' locks',
|
345 | 401 | NULL AS query_text
|
346 | | - FROM lock_types AS lt; |
| 402 | + FROM lock_types AS lt |
| 403 | + OPTION ( RECOMPILE ); |
| 404 | + |
347 | 405 |
|
348 | 406 | /*Check 7 gives you more info queries for sp_BlitzCache */
|
349 | 407 | INSERT #deadlock_findings ( check_id, database_name, object_name, finding_group, finding, query_text )
|
|
362 | 420 | NULL AS query_text
|
363 | 421 | FROM #deadlock_stack AS ds
|
364 | 422 | JOIN #deadlock_owner_waiter AS dow
|
365 | | - ON dow.owner_id = ds.id; |
| 423 | + ON dow.owner_id = ds.id |
| 424 | + OPTION ( RECOMPILE ); |
| 425 | + |
366 | 426 |
|
367 | 427 | /*Check 8 gives you more info queries for sp_BlitzCache */
|
368 | 428 | WITH bi AS (
|
|
384 | 444 | ', @TableName = ' + QUOTENAME(bi.table_name, '''') +
|
385 | 445 | ';' AS finding,
|
386 | 446 | NULL AS query_text
|
387 | | - FROM bi; |
| 447 | + FROM bi |
| 448 | + OPTION ( RECOMPILE ); |
| 449 | + |
388 | 450 |
|
389 | 451 | /*Check 9 gets total deadlock wait time per database*/
|
390 | 452 | WITH wait_time AS (
|
|
404 | 466 | + ' [d/h/m/s] of deadlock wait time.',
|
405 | 467 | NULL AS query_text
|
406 | 468 | FROM wait_time AS wt
|
407 | | - GROUP BY wt.database_name; |
| 469 | + GROUP BY wt.database_name |
| 470 | + OPTION ( RECOMPILE ); |
408 | 471 |
|
409 | 472 |
|
410 | 473 | /*Thank you goodnight*/
|
|
499 | 562 | JOIN (SELECT TOP 1 * FROM #deadlock_process AS dp) AS owner
|
500 | 563 | ON owner.id = dow.owner_id
|
501 | 564 | JOIN (SELECT TOP 1 * FROM #deadlock_process AS dp) AS waiter
|
502 | | - ON waiter.id = dow.owner_id; |
| 565 | + ON waiter.id = dow.owner_id |
| 566 | + OPTION ( RECOMPILE ); |
503 | 567 |
|
504 | 568 |
|
505 | 569 |
|
506 | 570 | SELECT df.check_id, df.database_name, df.object_name, df.finding_group, df.finding, df.query_text
|
507 | 571 | FROM #deadlock_findings AS df
|
508 | | - ORDER BY df.check_id; |
| 572 | + ORDER BY df.check_id |
| 573 | + OPTION ( RECOMPILE ); |
509 | 574 |
|
510 | 575 |
|
511 | 576 | IF @Debug = 1
|
512 | 577 | BEGIN
|
513 | 578 |
|
514 | 579 | SELECT '#deadlock_data' AS table_name, *
|
515 | | - FROM #deadlock_data AS dd; |
| 580 | + FROM #deadlock_data AS dd |
| 581 | + OPTION ( RECOMPILE ); |
516 | 582 |
|
517 | 583 | SELECT '#deadlock_resource' AS table_name, *
|
518 | | - FROM #deadlock_resource AS dr; |
| 584 | + FROM #deadlock_resource AS dr |
| 585 | + OPTION ( RECOMPILE ); |
519 | 586 |
|
520 | 587 | SELECT '#deadlock_owner_waiter' AS table_name, *
|
521 | | - FROM #deadlock_owner_waiter AS dow; |
| 588 | + FROM #deadlock_owner_waiter AS dow |
| 589 | + OPTION ( RECOMPILE ); |
522 | 590 |
|
523 | 591 | SELECT '#deadlock_process' AS table_name, *
|
524 | | - FROM #deadlock_process AS dp; |
| 592 | + FROM #deadlock_process AS dp |
| 593 | + OPTION ( RECOMPILE ); |
525 | 594 |
|
526 | 595 | SELECT '#deadlock_stack' AS table_name, *
|
527 | | - FROM #deadlock_stack AS ds; |
| 596 | + FROM #deadlock_stack AS ds |
| 597 | + OPTION ( RECOMPILE ); |
528 | 598 |
|
529 | 599 | END; -- End debug
|
530 | 600 |
|
531 | 601 | END; --Final End
|
532 | | -GO |
533 | | - |
534 | | - |
535 | | - |
536 | | - |
537 | 602 |
|
| 603 | +GO |
538 | 604 |
|
0 commit comments