Πώς μπορούμε να λαμβάνουμε email όποτε έχουμε υψηλό CPU Usage στον SQL Server

Πώς μπορούμε να λαμβάνουμε email όποτε έχουμε υψηλό CPU Usage στον SQL Server
Πώς μπορούμε να λαμβάνουμε email όποτε έχουμε υψηλό CPU Usage στον SQL Server

Σε αυτό το άρθρο θα δούμε ένα script που δημιουργεί ένα SQL Server Agent Job το οποίο θα μας ενημερώνει με email όποτε το CPU ξεπεράσει ένα threshold. Την πληροφορία την αντλέι όχι από performance counters του λειτουργικού αλλά από το default Extended Event του system_health που υπάρχει στην κάθε εγκατάσταση SQL Server.

Τα βήματα

Για αρχή θα πρέπει να έχουμε ενεργοποιήσει το Database Mail στον SQL Server. Το πως γίνεται αυτό το έχουμε δει σε αυτό το άρθρο.

Το Transact SQL Script

Με το παρακάτω script που έχω ετοιμάσει, θα φτιαχτεί ένα SQL Server Agent Job το οποίο θα τρέχει άνα 5 λεπτά και θα ελέγχει πόσο είναι το CPU Usage μέσα από το system_health Extended Event. Αν ξεπερνάει το threshold που έχουμε ορίσει στον κώδικα θα στέλνει email με το profile που έχουμε ορίσει.

Τις μόνες πληροφορίες που χρειάζεται να αλλάξουμε ανά περίπτωση είναι (γραμμή 59):

IF  cast(@usage as int) > 95    <----- The limit / threshold of CPU Usage that we want to send us emails above
begin
	exec msdb.dbo.sp_send_dbmail
	@profile_name = ''gmail'',       <----- The profile name we made to send email in the first step
	@recipients = ''info@dataplatform.gr'',    <----- And the recipients of the email
	@subject = @sub,
	@body = @bod;
end;

Αφού κάνουμε τις παραπάνω τροποποιήσεις στο παρακάτω script, μένει απλά να τρέξουμε σε ένα καινούργιο query window στο instance:

USE [msdb]
GO

/****** Object:  Job [Alert for high CPU]    Script Date: 29/10/2021 05:00:31 ìì ******/
BEGIN TRANSACTION
DECLARE @ReturnCode INT
SELECT @ReturnCode = 0
/****** Object:  JobCategory [[Uncategorized (Local)]]    Script Date: 29/10/2021 05:00:31 ìì ******/
IF NOT EXISTS (SELECT name FROM msdb.dbo.syscategories WHERE name=N'[Uncategorized (Local)]' AND category_class=1)
BEGIN
EXEC @ReturnCode = msdb.dbo.sp_add_category @class=N'JOB', @type=N'LOCAL', @name=N'[Uncategorized (Local)]'
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback

END

DECLARE @jobId BINARY(16)
EXEC @ReturnCode =  msdb.dbo.sp_add_job @job_name=N'Alert for high CPU', 
		@enabled=1, 
		@notify_level_eventlog=0, 
		@notify_level_email=0, 
		@notify_level_netsend=0, 
		@notify_level_page=0, 
		@delete_level=0, 
		@description=N'No description available.', 
		@category_name=N'[Uncategorized (Local)]', 
		@owner_login_name=N'sa', @job_id = @jobId OUTPUT
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
/****** Object:  Step [step1]    Script Date: 29/10/2021 05:00:31 ìì ******/
EXEC @ReturnCode = msdb.dbo.sp_add_jobstep @job_id=@jobId, @step_name=N'step1', 
		@step_id=1, 
		@cmdexec_success_code=0, 
		@on_success_action=1, 
		@on_success_step_id=0, 
		@on_fail_action=2, 
		@on_fail_step_id=0, 
		@retry_attempts=0, 
		@retry_interval=0, 
		@os_run_priority=0, @subsystem=N'TSQL', 
		@command=N'set ansi_warnings on
go
set ansi_padding on
go
set quoted_identifier on
go
declare 
@usage  int,
@sub nvarchar(max),
@bod nvarchar(max)
set @usage =
(		SELECT 100-avg(record.value(''(./Record/SchedulerMonitorEvent/SystemHealth/SystemIdle)[1]'', ''INT'')) as ''Cpu Usage %''
					FROM ( 
                        SELECT top 5 CONVERT(xml, record) AS [record],dateadd (ms,timestamp - (select ms_ticks from sys.dm_os_sys_info),getdate()) as ''Time''
						FROM sys.dm_os_ring_buffers
                        WHERE ring_buffer_type = N''RING_BUFFER_SCHEDULER_MONITOR''
                        AND record LIKE ''%<SystemHealth>%''
						order by time desc) AS x) ;
set @sub = (select ''SQL Server Alert System: High CPU Usage at '' + @@servername);
set @bod = (select ''DESCRIPTION: At '' + cast(getdate() as nvarchar) +'' on SQL Server '' + @@servername +'', CPU usage was '' +cast(@usage as nvarchar)+ ''%!!!!'');
IF  cast(@usage as int) > 95
begin
	exec msdb.dbo.sp_send_dbmail
	@profile_name = ''gmail'',
	@recipients = ''info@dataplatform.gr'',
	@subject = @sub,
	@body = @bod;
end;
', 
		@database_name=N'master', 
		@flags=0
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
EXEC @ReturnCode = msdb.dbo.sp_update_job @job_id = @jobId, @start_step_id = 1
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
EXEC @ReturnCode = msdb.dbo.sp_add_jobschedule @job_id=@jobId, @name=N'daily', 
		@enabled=1, 
		@freq_type=4, 
		@freq_interval=1, 
		@freq_subday_type=4, 
		@freq_subday_interval=5, 
		@freq_relative_interval=0, 
		@freq_recurrence_factor=0, 
		@active_start_date=20211029, 
		@active_end_date=99991231, 
		@active_start_time=0, 
		@active_end_time=235959, 
		@schedule_uid=N'df24cb48-55e9-436a-a0de-56d4dd5139a3'
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
EXEC @ReturnCode = msdb.dbo.sp_add_jobserver @job_id = @jobId, @server_name = N'(local)'
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
COMMIT TRANSACTION
GOTO EndSave
QuitWithRollback:
    IF (@@TRANCOUNT > 0) ROLLBACK TRANSACTION
EndSave:
GO


Όταν το τρέξουμε θα δούμε στον Object Explorer του SQL Server Management Studio ότι έχει δημιουργήσει ένα καινούργιο Job στον SQL Server Agent:

Πώς μπορούμε να λαμβάνουμε email όποτε έχουμε υψηλό CPU Usage στον SQL Server
01

Μετά από λίγο θα δούμε ότι έστειλε μόνο του χωρίς να κάνουμε κάτι άλλο email για High CPU Usage (για το παράδειγμα άλλαξα το threshold από πάνω από 95% σε 10% για να σταλεί):

Πώς μπορούμε να λαμβάνουμε email όποτε έχουμε υψηλό CPU Usage στον SQL Server
02

Πηγές:

Μοιράσου το

Αφήστε μία απάντηση