Lassen Sie einen Job beenden, wenn er nicht auf dem primären Replikat ausgeführt wird
In diesem Fall benötigt jeder Job auf beiden Servern einen der beiden folgenden Codeausschnitte als Schritt 1:
Nach Gruppenname prüfen:
IF master.dbo.svf_AgReplicaState('my_group_name')=0
raiserror ('This is not the primary replica.',2,1)
Nach Datenbanknamen prüfen:
IF master.dbo.svf_AgReplicaState('my_db_name')=0
raiserror ('This is not the primary replica.',2,1)
Wenn Sie diese zweite Variante verwenden, sollten Sie jedoch auf die Systemdatenbanken achten - per Definition können sie keiner Verfügbarkeitsgruppe angehören, sodass sie für diese immer fehlschlagen.
Beide Funktionen sind für Administratorbenutzer sofort einsatzbereit. Für Benutzer ohne Administratorrechte müssen Sie zusätzliche Berechtigungen hinzufügen, von denen eine hier vorgeschlagen wird :
GRANT VIEW SERVER STATE TO [user];
GRANT VIEW ANY DEFINITION TO [user];
Wenn Sie die Fehleraktion in diesem ersten Schritt auf Jobberichtserfolg beenden setzen, wird das Jobprotokoll nicht mit hässlichen roten Kreuzzeichen gefüllt. Für den Hauptjob werden sie stattdessen in gelbe Warnzeichen umgewandelt.
Nach unserer Erfahrung ist dies nicht ideal. Wir haben diesen Ansatz zunächst gewählt, jedoch schnell den Überblick über die Suche nach Jobs verloren, bei denen tatsächlich ein Problem aufgetreten ist, da alle sekundären Replikatjobs das Jobprotokoll mit Warnmeldungen überfüllten.
Was wir dann wollten, ist:
Proxy-Jobs
Wenn Sie dieses Konzept übernehmen, müssen Sie tatsächlich zwei Jobs pro Aufgabe erstellen, die Sie ausführen möchten. Der erste ist der "Proxy-Job", der prüft, ob er auf dem primären Replikat ausgeführt wird. Wenn dies der Fall ist, wird der "Arbeiterjob" gestartet. Wenn dies nicht der Fall ist, wird er ordnungsgemäß beendet, ohne das Protokoll mit Warn- oder Fehlermeldungen zu überladen.
Ich persönlich mag die Idee, zwei Jobs pro Task auf jedem Server zu haben, nicht, aber ich denke, dass sie auf jeden Fall besser zu warten sind, und Sie müssen die Fehleraktion des Schritts nicht auf Erfolg beim Beenden der Jobberichterstellung setzen , was ein bisschen ist peinlich.
Für die Jobs haben wir ein Namensschema übernommen. Der Proxy-Job wird gerade aufgerufen {put jobname here}
. Der Arbeiterjob wird aufgerufen {put jobname here} worker
. Dadurch ist es möglich, das Starten des Worker-Jobs vom Proxy aus zu automatisieren. Zu diesem Zweck habe ich den beiden Master-Datenbanken die folgende Prozedur hinzugefügt:
CREATE procedure [dbo].[procStartWorkerJob](@jobId uniqueidentifier, @availabilityGroup sysname, @postfix sysname = ' worker') as
declare @name sysname
if dbo.svf_AgReplicaState(@availabilityGroup)=0
print 'This is not the primary replica.'
else begin
SELECT @name = name FROM msdb.dbo.sysjobs where job_id = @jobId
set @name = @name + @postfix
if exists(select name from msdb.dbo.sysjobs where name = @name)
exec msdb.dbo.sp_start_job @name
else begin
set @name = 'Job '''+@name+''' not found.'
raiserror (@name ,2,1)
end
end
GO
Hierbei wird die svf_AgReplicaState
oben gezeigte Funktion verwendet. Sie können diese einfach ändern, um den Datenbanknamen zu überprüfen, indem Sie die andere Funktion aufrufen.
Innerhalb des einzigen Schritts des Proxy-Jobs nennen Sie es folgendermaßen:
exec procStartWorkerJob $(ESCAPE_NONE(JOBID)), '{my_group_name}'
Hierbei werden die hier und hier gezeigten Tokens verwendet , um die aktuelle Job-ID abzurufen. Die Prozedur ruft dann den aktuellen Jobnamen von msdb ab, hängt worker
ihn an und startet den Worker-Job mit sp_start_job
.
Obwohl dies immer noch nicht ideal ist, werden die Auftragsprotokolle übersichtlicher und wartbarer als bei der vorherigen Option. Sie können den Proxy-Job auch immer mit einem Sysadmin-Benutzer ausführen lassen, sodass das Hinzufügen zusätzlicher Berechtigungen nicht erforderlich ist.