Monitorare SQL Server: le notifiche proattive

Datamaze
07.06.23 11:37 AM Comment(s)
Nell’ambito del monitoraggio di SQL Server le notifiche proattive possono rivelarsi molto utili.               

Con l’utilizzo e l’aumento di complessità di un’infrastruttura database, si possono verificare numerose problematiche, come:              
  • Il registro delle transazioni è pieno
  • Il database è molto lento
  • L'ultimo backup risale a diversi giorni addietro
  • Il sistema è bloccato e le query non funzionano
  • Si verificano dei deadlock

Sono disponibili sul mercato svariati strumenti per il monitoraggio, come ad esempio Paessler PRTG, Quest Foglight, Solarwinds, Red Gate SQL Monitor e altri. Questi strumenti forniscono una visualizzazione unificata in cui sono visibili tutti gli avvisi in un unico colpo d'occhio. Solitamente la maggior parte di questi strumenti sono preconfigurati e per iniziare ad utilizzarli è sufficiente indicare su quale server attivare il monitoraggio.               

Vediamo per ogni problematica come un Database Administrator può intervenire per risolvere i problemi o, preferibilmente, anticipare le criticità.              

Sfruttare i log

Un DBA deve scansionare periodicamente l'errorlog per verificare se ci sono errori, ma si tratta di un processo che può essere automatizzato creando un job di SQL Agent che viene eseguito ogni cinque minuti e che controlla se ci sono stati errori dall'ultima esecuzione. Può quindi essere utilizzata la stored procedure xp_readerrorlog per leggere il log degli errori da SQL Server SQL tramite T-SQL, inviare i risultati via e-mail, inserire il risultato in una tabella che viene mostrata su una dashboard.

-- Questo conterrà le righe
CREATE TABLE #ErrorLog (
	LogDate DATETIME
	,ProcessInfo VARCHAR(10)
	,ErrorMessage VARCHAR(Max)
	)

-- Dump del log degli errori nella tabella
INSERT INTO #ErrorLog
EXEC master.dbo.xp_readerrorlog

-- Elimina tutto più vecchio di cinque minuti
-- idealmente memorizzerai la data massima dell'ultima esecuzione
DELETE #ErrorLog
WHERE LogDate < DATEADD(mi, - 5, GETDATE())

-- Backup non riusciti
SELECT *
FROM #ErrorLog

Altre possibili problematiche

Il registro delle transazioni è pieno

È fondamentale assicurarsi di sapere in anticipo quando si sta per esaurire lo spazio. In caso di Transaction Log Full, è possibile seguire la procedura suggerita da Microsoft.


Il database è molto lento

Ci sono diverse cose che potrebbero provocare rallentamenti, ad esempio: 

  • Qualcuno ha deciso di fare un backup di un database da 1 TB durante la giornata lavorativa.
  • L'aggiornamento delle statistiche dei job è ancora in esecuzione.
  • Le statistiche sono obsolete e non sono state aggiornate da tempo.
  • La scansione del virus causa problemi in quanto non sono stati ignorati i file del database.
  • Qualcuno ha deciso di interrogare tutti i dati in una volta sola.

Con strumenti come Quest Foglight, Confio Ignite, Red Gate SQL Monitor o simili, è possibile vedere quale query è stata eseguita in quale momento, cosa ha fatto e per quanto tempo è stata eseguita. Si può utilizzare anche sp_who2, la colonna BlkBy e DBCC INPUTBUFFER per vedere cosa sta succedendo. La causa potrebbe anche essere l’hardware, occorre perciò assicurarsi che gli IO siano in buone condizioni e controllare l'eventlog per eventuali indizi.


L'ultimo backup risale a diversi giorni addietro

La query seguente restituirà l’ultimo momento in cui è stato eseguito il backup per tutti i database o visualizzerà MAI se non è stato eseguito il backup:

SELECT s.Name AS NomeDatabase
	,'Il backup del database è stato eseguito su ' + CASE 
		WHEN MAX(b.backup_finish_date) IS NULL
			THEN 'MAI!!!'
		ELSE CONVERT(VARCHAR(12), (MAX(b.backup_finish_date)), 101)
		END AS UltimoTempoBackUp
FROM sys.sysdatabases s
LEFT OUTER JOIN msdb.dbo.backupset b ON b.database_name = s.name
GROUP BY s.Name

Ecco come apparirà l'output:

NomeDatabase UltimoTempoBackUp

model Il backup del database è stato eseguito il MAI!!!

msdb Il backup del database è stato eseguito il 12/10/2012

ReportServer Il backup del database è stato eseguito il MAI!!!

 

Tutti i database dovrebbero sempre essere oggetto di regolare backup ed è importante controllare il file di log per eventuali backup falliti.


Il sistema è bloccato e le query non funzionano

Di solito questo indica che da qualche parte c'è una transazione aperta che non è stata completata o che qualcuno ha eseguito la parte BEGIN TRAN ma non ha mai fatto un COMMIT o ROLLBACK.

Alcune persone riavviano il server per "risolvere" il problema, ma in questo modo non si può capire la causa e se il problema si verificherà nuovamente.

Ecco come simulare una transazione aperta:
In una finestra di query esegui questo, sostituire SomeTable con un nome di tabella reale.
BEGIN TRAN

SELECT TOP 1 *
FROM SomeTable WITH (
		UPDLOCK
		,HOLDLOCK
		)

Si otterrà un messaggio che la query è stata completata con successo.

In un'altra finestra eseguire:

SELECT TOP 1 *
FROM SomeTable WITH (
		UPDLOCK
		,HOLDLOCK
		)

Questa query non restituirà nulla a meno che la prima non sia stata oggetto di committ o rollback. 

Ora eseguire questa query qui sotto, la prima colonna dovrebbe avere il testo AWAITING COMMAND

SELECT sys.cmd
	,sys.last_batch
	,lok.resource_type
	,lok.resource_subtype
	,DB_NAME(lok.resource_database_id)
	,lok.resource_description
	,lok.resource_associated_entity_id
	,lok.resource_lock_partition
	,lok.request_mode
	,lok.request_type
	,lok.request_status
	,lok.request_owner_type
	,lok.request_owner_id
	,lok.lock_owner_address
	,wat.waiting_task_address
	,wat.session_id
	,wat.exec_context_id
	,wat.wait_duration_ms
	,wat.wait_type
	,wat.resource_address
	,wat.blocking_task_address
	,wat.blocking_session_id
	,wat.blocking_exec_context_id
	,wat.resource_description
FROM sys.dm_tran_locks lok
JOIN sys.dm_os_waiting_tasks wat ON lok.lock_owner_address = wat.resource_address
JOIN sys.sysprocesses sys ON wat.blocking_session_id = sys.spid

Le voci blocking_session_id e un session_id indicano quale session_id sta venendo bloccato. Ora si può verificare che la sessione della transazione sta bloccando l'altro ID.

Tornare alla prima finestra di comando ed eseguire un rollback:

ROLLBACK

 

Anche la query che aveva il secondo select dovrebbe a questo punto venire completata; se si esegue la query che controlla le attese dovrebbe essere funzionare anch’essa.

Si sarebbe potuto ottenere lo stesso risultato eseguendo sp_who2, guardando la colonna BlkBy, scoprendo cosa sta facendo quella sessione eseguendo DBCC INPUTBUFFER(session_id) con quella session_id.


Si verificano deadlock

È possibile impostare una notifica via e-mail quando si verificano deadlock. Clicca qui per la guida (in inglese). 


Questo articolo è stato tratto dal blog SQL Server Code, Tips and Tricks.


di Alice Sella, pubblicato il 7 giugno 2023.