Powershell in un job MSSQL – Error logging – Gestiamo gli errori con le funzioni standard di SQL

Nella cassetta degli attrezzi di un sistemista che si rispetti non può mancare Powershell.
Io personalmente lo adoro e mi permette di automatizzare molti task sistemistici.

Qui sotto riporto un piccolo esempio per integrare uno script Powershell in un job SQL:

$ErrorActionPreference = "Stop"
try{

QUI IL MIO CODICE O LA CHIAMATA AL MIO PS1  

   }
catch{
   Throw
}

Impostato in questa maniera, siamo in grado di intercettare nel job history di SQL le eventuali eccezioni ed errori del nostro script, cosa molto utile se lo si schedula in orario non lavorativo, con alerting automatico in caso di abend (Abnormal End)

Microsoft SQL – Database in AAG – Abilitiamo o disabilitiamo servizi Windows sui nodi

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!