Fare terminare un lavoro se non viene eseguito sulla replica primaria
In questo caso, ogni lavoro su entrambi i server richiede uno dei due seguenti frammenti di codice come Passaggio 1:
Controlla per nome del gruppo:
IF master.dbo.svf_AgReplicaState('my_group_name')=0
raiserror ('This is not the primary replica.',2,1)
Verifica per nome del database:
IF master.dbo.svf_AgReplicaState('my_db_name')=0
raiserror ('This is not the primary replica.',2,1)
Se usi questo secondo, fai attenzione ai database di sistema - per definizione non possono far parte di nessun gruppo di disponibilità, quindi falliranno sempre per quelli.
Entrambi funzionano immediatamente per gli utenti amministratori. Per gli utenti non amministratori, devi aggiungere ulteriori autorizzazioni, una delle quali suggerita qui :
GRANT VIEW SERVER STATE TO [user];
GRANT VIEW ANY DEFINITION TO [user];
Se imposti l'azione di errore su Esci dal processo di segnalazione del successo in questo primo passaggio, non otterrai il registro lavori pieno di brutti segni della croce rossa, per il lavoro principale si trasformeranno invece in segnali di avvertimento gialli.
Dalla nostra esperienza, questo non è l'ideale. Inizialmente abbiamo adottato questo approccio, ma abbiamo perso rapidamente traccia per quanto riguarda la ricerca di lavori che in realtà avevano un problema, perché tutti i lavori di replica secondari ingombravano il registro dei lavori con messaggi di avviso.
Ciò che abbiamo scelto è:
Processi proxy
Se adotti questo concetto, dovrai effettivamente creare due lavori per ogni attività che desideri eseguire. Il primo è il "processo proxy" che controlla se viene eseguito sulla replica primaria. In tal caso, avvia il "lavoro di lavoro", in caso contrario, termina semplicemente senza ingombrare il registro con messaggi di avviso o di errore.
Mentre personalmente non mi piace l'idea di avere due lavori per attività su ogni server, penso che sia sicuramente più gestibile e non devi impostare l'azione di errore del passaggio per chiudere il processo di segnalazione dei lavori , che è un po ' imbarazzante.
Per i lavori, abbiamo adottato uno schema di denominazione. Il processo proxy è appena chiamato {put jobname here}
. Viene chiamato il lavoro lavoratore {put jobname here} worker
. Ciò consente di automatizzare l'avvio del processo di lavoro dal proxy. Per fare ciò, ho aggiunto la seguente procedura a entrambi i master dbs:
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
Questo utilizza la svf_AgReplicaState
funzione mostrata sopra, puoi facilmente cambiarla per controllare usando il nome del database invece chiamando l'altra funzione.
Dall'unico passaggio del processo proxy, lo si chiama in questo modo:
exec procStartWorkerJob $(ESCAPE_NONE(JOBID)), '{my_group_name}'
Questo utilizza i token come mostrato qui e qui per ottenere l'ID del lavoro corrente. La procedura quindi ottiene il nome del lavoro corrente da msdb, lo aggiunge worker
e avvia il lavoro di lavoro utilizzando sp_start_job
.
Sebbene ciò non sia ancora ideale, mantiene i registri lavori più ordinati e gestibili rispetto all'opzione precedente. Inoltre, è sempre possibile eseguire il processo proxy con un utente sysadmin, quindi non è necessario aggiungere ulteriori autorizzazioni.