Quella del cluster database di tipo AAG (Always-on Availability Group) è una delle configurazioni più resilienti di SQL e tramite una configurazione a nodo 1+N che se bilanciata bene permette una grossa resilienza ed un importante uptime.
Introduzione
Nell’AAG, uno dei nodi è sempre il primario, i “+N” (che potrebbe essere uno o molteplici) rimangono in standby con una replica puntuale dei DB. Una delle caratteristiche più interessanti della configurazione AAG è il failover automatico, che consiste nel cambio ruolo automatico a fronte di un problema tecnico. In questo scenario potrebbe essere necessario attivare dei servizi ancillari alla macchina, come ad esempio uno schedulatore esterno (es IWS), uno strumento di file transfer o un qualsiasi agent.
Esempio di TSQL per Avviare o Arrestare dinamicamente un servizio in base al nodo in cui sta girando l’istanza
di seguito, un piccolo POC con un esempio di TSQL per avviare o disabilitare un servizio a fronte di un cambio ruolo di SQL:
DECLARE @primreplica VARCHAR(100);
DECLARE @ServiceName VARCHAR(128) = 'NOMESERVIZIO';
DECLARE @Status VARCHAR(MAX);
DECLARE @ServicesStatus TABLE
(
Status VARCHAR(50)
);
SELECT @primreplica = s.primary_replica
FROM sys.dm_hadr_availability_group_states s
JOIN sys.availability_groups ag
ON ag.group_id = s.group_id;
-- se dove sto girando è primario
IF UPPER(@primreplica) = UPPER(@@SERVERNAME)
BEGIN
INSERT @ServicesStatus
EXEC xp_servicecontrol N'QUERYSTATE', @ServiceName;
SELECT @Status = Status
FROM @ServicesStatus;
--select @Status
IF @Status <> 'Running.'
BEGIN
EXEC xp_servicecontrol N'Start', @ServiceName;
END;
END;
ELSE
BEGIN
INSERT @ServicesStatus
EXEC xp_servicecontrol N'QUERYSTATE', @ServiceName;
SELECT @Status = Status
FROM @ServicesStatus;
--select @Status
IF @Status = 'Running.'
BEGIN
EXEC xp_servicecontrol N'Stop', @ServiceName;
END;
END;
Personalmente, l’ho schedulato in un job SQL sempre attivo su tutti i nodi (lo stesso JOB contiene lo statement per abilitare o disabilitare i JOB SQL).
Andiamo un poco più in drill-down:
Tramite la select di seguito riportata, stabilisco se sto girando sulla replica primaria o sul secondario, andando a confrontare il nome del server su cui sta girando l’istanza (tramite la funzione SQL @@SERVERNAME) ed il nome della replica primaria sulle tabelle di sistema che regolano l’AAG:
SELECT @primreplica = s.primary_replica
FROM sys.dm_hadr_availability_group_states s
JOIN sys.availability_groups ag
ON ag.group_id = s.group_id;
-- se dove sto girando è primario
IF UPPER(@primreplica) = UPPER(@@SERVERNAME)
Con un semplice ciclo IF/ELSE tramite una tabella di appoggio e la StoreProcedure EXEC xp_servicecontrol determino se il servizio sta girando o meno ed in base alla risposta ed al server, avvio o disabilito il servizio:
INSERT @ServicesStatus
EXEC xp_servicecontrol N'QUERYSTATE', @ServiceName;
SELECT @Status = Status
FROM @ServicesStatus;
--select @Status
IF @Status <> 'Running.'
BEGIN
EXEC xp_servicecontrol N'Start', @ServiceName;
END;
Sintassi di xp_servicecontrol
EXEC xp_servicecontrol ‘Querystat|Start|Stop’,’servicename’
La store in oggetto accetta due parametri, il primo è l’operazione da svolgere:
- Querystat – Restituisce lo stato di un servizio.
- Start – Avvia un servizio.
- Stop – Arresta un servizio.
Il secondo, il nome del servizio.
Enjoy!