SQL Server Proactive Memory Monitoring and Alerting Setup
Objective
Implement a proactive monitoring and alerting solution for SQL Server that:
• Tracks per-query memory grants
• Alerts when a query requests excessive memory
• Notifies when total memory usage is approaching critical levels
• Provides query-level insight in email alerts
Monitoring Components
1. SQL Server DMV Queries
Query: Total vs Target Server Memory
SELECT
(SELECT cntr_value FROM sys.dm_os_performance_counters
WHERE counter_name = 'Total Server Memory (KB)' AND object_name LIKE
'%Memory Manager%') AS TotalMemoryKB,
(SELECT cntr_value FROM sys.dm_os_performance_counters
WHERE counter_name = 'Target Server Memory (KB)' AND object_name LIKE
'%Memory Manager%') AS TargetMemoryKB;
Query: Query Memory Grants
SELECT TOP 5
session_id,
requested_memory_kb / 1024 AS RequestedMB,
granted_memory_kb / 1024 AS GrantedMB,
LEFT(text, 200) AS QueryText
FROM sys.dm_exec_query_memory_grants g
CROSS APPLY sys.dm_exec_sql_text(g.sql_handle)
ORDER BY requested_memory_kb DESC;
PowerShell Monitoring Script
$server = "YourServer\Instance"
$db = "master"
$thresholdPercent = 85
$memoryRequestAlertMB = 300
$emailTo = "
[email protected]"
$emailFrom = "
[email protected]"
$smtpServer = "smtp.domain.com"
# Load current memory usage
$memoryQuery = @"
SELECT
(SELECT cntr_value FROM sys.dm_os_performance_counters
WHERE counter_name = 'Total Server Memory (KB)' AND object_name LIKE
'%Memory Manager%') AS TotalMemoryKB,
(SELECT cntr_value FROM sys.dm_os_performance_counters
WHERE counter_name = 'Target Server Memory (KB)' AND object_name LIKE
'%Memory Manager%') AS TargetMemoryKB;
"@
$memory = Invoke-Sqlcmd -ServerInstance $server -Database $db -Query
$memoryQuery
$total = $memory.TotalMemoryKB
$target = $memory.TargetMemoryKB
$percentUsed = [math]::Round(($total / $target) * 100, 2)
# Load memory grants
$grantsQuery = @"
SELECT TOP 5
session_id,
requested_memory_kb / 1024 AS RequestedMB,
granted_memory_kb / 1024 AS GrantedMB,
LEFT(text, 200) AS QueryText
FROM sys.dm_exec_query_memory_grants g
CROSS APPLY sys.dm_exec_sql_text(g.sql_handle)
ORDER BY requested_memory_kb DESC;
"@
$grants = Invoke-Sqlcmd -ServerInstance $server -Database $db -Query
$grantsQuery
# Compose HTML for grants
$html = "<h3>Top 5 Memory Grant Queries</h3><table
border='1'><tr><th>SessionID</th><th>Requested (MB)</th><th>Granted
(MB)</th><th>Query</th></tr>"
foreach ($row in $grants) {
$html +=
"<tr><td>$($row.session_id)</td><td>$($row.RequestedMB)</td><td>$($row.Grante
dMB)</td><td>$($row.QueryText)</td></tr>"
}
$html += "</table>"
# Add memory stats
$body = @"
<h2> SQL Server Memory Pressure Alert</h2>
<p><b> Total Server Memory (KB):</b> $total<br>
<b> Target Server Memory (KB):</b> $target<br>
<b> Memory In Use (%):</b> $percentUsed%</p>
$html
<p><b> WARNING:</b> If a new query requests more than
<b>$memoryRequestAlertMB MB</b>, SQL Server may enter memory pressure and
block new memory grants.</p>
"@
# Send only if used memory is above threshold
if ($percentUsed -gt $thresholdPercent) {
Send-MailMessage -To $emailTo -From $emailFrom -Subject " SQL Memory
Alert - $percentUsed% Used" -Body $body -BodyAsHtml -SmtpServer $smtpServer
}
Deployment Options
• Schedule via Task Scheduler to run every 5 mins
• Convert to Windows Service via NSSM or WinSW
• Log alerts to SQL table for trend tracking (optional enhancement)
Notes
• Adjust memory thresholds based on server capacity and workload
• Include authentication and credential security for automation
• Ensure DBMail and Invoke-Sqlcmd are properly configured on host