Hantering av SQL Agent jobb när man har AlwaysOn Availability Groups

Oopps! Upgrade your browser pretty please. Oopps! Upgrade your browser pretty please.

Det man exempelvis måste tänka på är att det inte finns någon automatisk synkronisering av objekt utanför användardatabaserna till exempel logins, jobb, länkade servrar, server triggers med mera. Detta är något man manuellt måste lägga upp på respektive server i AlwaysOn uppsättningen.

Förutom logins så är kanske det mest uppenbara alla SQL Agent jobb som man har. Här har vi några utmaningar:

  1. Se till så att alla jobb faktiskt finns på resp server.
  2. Se till så att jobben endast körs där de skall köras/är möjliga att köra.
  3. Se till så att rätt jobb är enablade.

Jag tänker här fokusera på punkt 2. övriga punkter får bli framtida blogginlägg.

Om vi bortser från det faktum att man faktiskt kan köra backuper och integrity-checks mot sekundära replikas om Availability gruppen är rätt inställd, och man har betalat rätt licenspeng, så har man ofta ett mer eller mindre stort antal jobb som bara kan/skall köras på den primära servern. Problemet blir då vid en eventuell failover. Då måste man se till så att jobben istället kör på den sekundära/nya primära servern.

Jag själv har testat ett par olika varianter för att komma runt problemet:

1. Man har ett jobb som ser till att enabla/disabla rätt jobb vid failover. Denna lösning är lite knepig eftersom den kräver ett par saker:

  • Att man har koll på vilka jobb som är enablade/disablade.
  • Att jobbet som enablar/disablar andra jobb faktiskt körs vid en failover. Antingen triggar man det via någon alert eller så kör man jobbet manuellt (förutsätter att man har en kontrollerad manuell failover)

2. Man lägger till ett första steg i alla jobb som kontrollerar om den aktuella servern är primär, om inte så skall jobbet inte köras. Denna lösning är lite renare eftersom jobben alltid är enablade. Några saker krävs även här:

  • Man måste som sagt kontrollera om servern är primär eller sekundär. From SQL Server 2014 kan man använda sig av funktionen: sys.fn_hadr_is_primary_replica(‘DatabasNamn’). Om man fortfarande kör SQL Server 2012 får man se till att gräva fram rätt information på egen hand.
  • Ovanstående kontroll måste sedan läggas in i ett jobbsteg som adderas till alla jobb. Om kontrollen resulterar i att vi inte kör på den primära servern stoppas jobbet genom att köra sp_stop_job och jobbet avslutas innan ordinarie logik körs.
  • Om man har många jobb på sin server kan det vara tidskrävande att manuellt lägga till ett jobbsteg till alla jobb. För att slippa det kan man med lite kodning relativt enkelt automatisera det.

Exempel, följande kod kontrollerar om vi kör på den primära noden och, om inte, stoppar jobbet.

Om man kör SQL Server 2014:

IF sys.fn_hadr_is_primary_replica('DatabasNamn') <> 1
BEGIN
   EXEC msdb.dbo.sp_stop_job @Job_Name = 'JobbNamn'
END

Eller om man kör SQL Server 2012:

IF (SELECT RS.role_desc 
FROM sys.dm_hadr_availability_replica_cluster_states CS
INNER JOIN sys.dm_hadr_availability_replica_states RS on RS.replica_id = CS.replica_id
WHERE CS.replica_server_name = @@SERVERNAME) = 'SECONDARY'
BEGIN
   EXEC msdb.dbo.sp_stop_job @job_name = 'JobbNamn'
END

Allt som nu återstår är att lägga in någon av ovan kodsnutt i respektive jobb som första steg och sedan se till så att rätt jobb är enablade.