Skip to content

Commit 344fff5

Browse files
Fix sp_PerfCheck deadlock check for sub-day uptime
The deadlock rate check (check_id 5103) divided the cumulative deadlock count by DATEDIFF(DAY, sqlserver_start_time, SYSDATETIME()) wrapped in NULLIF(..., 0). For any server whose uptime had not yet crossed a calendar-day boundary, DATEDIFF(DAY, ...) returned 0, NULLIF collapsed the divisor to NULL, and the resulting `rate > 9` comparison evaluated as UNKNOWN in the WHERE clause — which filters out the row, skipping the check entirely. The details CASE already had an ELSE branch formatted for "X deadlocks in Y hours since startup", but that branch was unreachable because WHERE never let a low-uptime row through. Rewrote the priority CASE and WHERE rate calculation to use DATEDIFF(SECOND, ...) with a *86400.0 scale factor, preserving the "more than 9 per day" threshold semantics while working for any uptime >= 1 second. DATEDIFF(SECOND) has ~68 years of safe range so overflow is not a concern. Verified on SQL Server 2022 with 3 days uptime and 725 deadlocks/day: the check now fires with priority 20 (High). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent ca2dbd8 commit 344fff5

1 file changed

Lines changed: 17 additions & 9 deletions

File tree

sp_PerfCheck/sp_PerfCheck.sql

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1007,17 +1007,25 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
10071007
)
10081008
SELECT
10091009
check_id = 5103,
1010+
/*
1011+
Rate is deadlocks-per-day, computed from DATEDIFF(SECOND, ...) rather than
1012+
DATEDIFF(DAY, ...). The DAY-based version rounded sub-day uptime to 0 and
1013+
the NULLIF then collapsed the whole expression to NULL, which evaluated as
1014+
UNKNOWN in the WHERE below and silently skipped the deadlock check for the
1015+
first calendar-day-boundary of server uptime. SECOND-based rate keeps the
1016+
threshold semantics identical for any uptime ≥ 1 second.
1017+
*/
10101018
priority =
10111019
CASE
10121020
WHEN
10131021
(
1014-
1.0 *
1015-
p.cntr_value /
1022+
p.cntr_value *
1023+
86400.0 /
10161024
NULLIF
10171025
(
10181026
DATEDIFF
10191027
(
1020-
DAY,
1028+
SECOND,
10211029
osi.sqlserver_start_time,
10221030
SYSDATETIME()
10231031
),
@@ -1027,13 +1035,13 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
10271035
THEN 20 /* High: >100 deadlocks/day */
10281036
WHEN
10291037
(
1030-
1.0 *
1031-
p.cntr_value /
1038+
p.cntr_value *
1039+
86400.0 /
10321040
NULLIF
10331041
(
10341042
DATEDIFF
10351043
(
1036-
DAY,
1044+
SECOND,
10371045
osi.sqlserver_start_time,
10381046
SYSDATETIME()
10391047
),
@@ -1074,13 +1082,13 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
10741082
AND p.cntr_value > 0
10751083
AND
10761084
(
1077-
1.0 *
1078-
p.cntr_value /
1085+
p.cntr_value *
1086+
86400.0 /
10791087
NULLIF
10801088
(
10811089
DATEDIFF
10821090
(
1083-
DAY,
1091+
SECOND,
10841092
osi.sqlserver_start_time,
10851093
SYSDATETIME()
10861094
),

0 commit comments

Comments
 (0)