Mettre fin à un travail s'il n'est pas exécuté sur le réplica principal
Dans ce cas, chaque travail sur les deux serveurs nécessite l'un des deux extraits de code suivants en tant qu'Étape 1:
Vérifier par nom de groupe:
IF master.dbo.svf_AgReplicaState('my_group_name')=0
raiserror ('This is not the primary replica.',2,1)
Vérifier par nom de base de données:
IF master.dbo.svf_AgReplicaState('my_db_name')=0
raiserror ('This is not the primary replica.',2,1)
Cependant, si vous utilisez ce second, méfiez-vous des bases de données système. Par définition, elles ne peuvent faire partie d'aucun groupe de disponibilité. Par conséquent, elles échoueront toujours.
Ces deux solutions sont prêtes à l'emploi pour les utilisateurs administrateurs. Pour les utilisateurs non-administrateurs, vous devez ajouter des autorisations supplémentaires, l'une d'entre elles suggérée ici :
GRANT VIEW SERVER STATE TO [user];
GRANT VIEW ANY DEFINITION TO [user];
Si vous définissez l'action d'échec sur Quitter le signalement du travail lors de cette première étape, le journal des travaux ne sera pas rempli de signes de croix rouges, mais pour le travail principal, ils deviendront des signes d'alerte jaunes.
D'après notre expérience, ce n'est pas idéal. Nous avons d’abord adopté cette approche, mais avons rapidement perdu le fil de la recherche des travaux qui posaient problème, car tous les travaux de réplicas secondaires encombraient le journal des travaux avec des messages d’avertissement.
Nous sommes ensuite allés chercher:
Proxy jobs
Si vous adoptez ce concept, vous devrez en fait créer deux tâches par tâche à exécuter. Le premier est le "travail proxy" qui vérifie s'il est exécuté sur le réplica principal. Si tel est le cas, il lance le "job worker", sinon, il se termine normalement sans encombrer le journal de messages d'avertissement ou d'erreur.
Personnellement, je n’aime pas l’idée d’avoir deux tâches par tâche sur chaque serveur, mais je pense que c’est nettement plus facile à gérer, et vous n’aurez pas à définir l’action en cas d’échec de l’étape Fin du rapport de tâche , ce qui est un peu gênant.
Pour les emplois, nous avons adopté un schéma de nommage. Le travail proxy est appelé {put jobname here}
. Le travail de travailleur s'appelle {put jobname here} worker
. Cela permet d'automatiser le démarrage du travail de travail à partir du proxy. Pour ce faire, j'ai ajouté la procédure suivante aux deux dbs maîtres:
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
Ceci utilise la svf_AgReplicaState
fonction montrée ci-dessus, vous pouvez facilement changer cela pour vérifier en utilisant le nom de la base de données à la place en appelant l'autre fonction.
À partir de la seule étape du travail de proxy, vous l'appelez comme suit:
exec procStartWorkerJob $(ESCAPE_NONE(JOBID)), '{my_group_name}'
Ceci utilise les jetons comme indiqué ici et ici pour obtenir l'identifiant du travail en cours. La procédure récupère ensuite le nom du travail actuel auprès de msdb, y est ajoutée worker
et démarre le travail de travail avec sp_start_job
.
Bien que cela ne soit toujours pas idéal, les journaux de travail sont plus propres et faciles à gérer que l’option précédente. En outre, le travail de proxy peut toujours être exécuté avec un utilisateur sysadmin. Il n'est donc pas nécessaire d'ajouter des autorisations supplémentaires.