Tornar um trabalho encerrado se não for executado na réplica primária
Nesse caso, todos os trabalhos nos dois servidores precisam de um dos dois trechos de código a seguir na Etapa 1:
Verifique pelo nome do grupo:
IF master.dbo.svf_AgReplicaState('my_group_name')=0
raiserror ('This is not the primary replica.',2,1)
Verifique pelo nome do banco de dados:
IF master.dbo.svf_AgReplicaState('my_db_name')=0
raiserror ('This is not the primary replica.',2,1)
Se você usar este segundo, tenha cuidado com os bancos de dados do sistema - por definição, eles não podem fazer parte de nenhum grupo de disponibilidade; portanto, eles sempre falham.
Ambos funcionam imediatamente para usuários administrativos. Para usuários não administradores, é necessário adicionar permissões extras, uma delas sugerida aqui :
GRANT VIEW SERVER STATE TO [user];
GRANT VIEW ANY DEFINITION TO [user];
Se você definir a ação de falha como Sair do relatório de trabalhos com êxito nesta primeira etapa, não receberá o registro de trabalhos cheio de sinais feios de cruz vermelha; para o trabalho principal, eles se transformarão em sinais de aviso amarelos.
De nossa experiência, isso não é o ideal. A princípio, adotamos essa abordagem, mas rapidamente perdemos o controle sobre a localização de tarefas que realmente tinham um problema, porque todas as tarefas de réplica secundária estavam repletas de logs de tarefas com mensagens de aviso.
O que procuramos então é:
Trabalhos de proxy
Se você adotar esse conceito, precisará criar dois trabalhos por tarefa que deseja executar. O primeiro é o "trabalho de proxy" que verifica se está sendo executado na réplica primária. Nesse caso, inicia o "trabalho do trabalhador"; caso contrário, termina normalmente sem desorganizar o log com mensagens de aviso ou erro.
Embora eu pessoalmente não goste da ideia de ter dois trabalhos por tarefa em todos os servidores, acho que é definitivamente mais sustentável, e você não precisa definir a ação de falha da etapa para Sair do sucesso do relatório de trabalhos , o que é um pouco desajeitado.
Para os trabalhos, adotamos um esquema de nomeação. O trabalho de proxy é apenas chamado {put jobname here}
. O trabalho do trabalhador é chamado {put jobname here} worker
. Isso torna possível automatizar o início do trabalho do trabalhador a partir do proxy. Para fazer isso, adicionei o seguinte procedimento aos dois dbs principais:
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
Isso utiliza a svf_AgReplicaState
função mostrada acima, você pode facilmente mudar isso para verificar usando o nome do banco de dados, chamando a outra função.
De dentro da única etapa do trabalho de proxy, você o chama assim:
exec procStartWorkerJob $(ESCAPE_NONE(JOBID)), '{my_group_name}'
Isso utiliza Tokens, como mostrado aqui e aqui, para obter o ID do trabalho atual. O procedimento obtém o nome do trabalho atual do msdb, anexa worker
a ele e inicia o trabalho do trabalhador usando sp_start_job
.
Embora isso ainda não seja o ideal, ele mantém os logs de tarefas mais organizados e com manutenção do que a opção anterior. Além disso, você sempre pode executar o trabalho de proxy com um usuário sysadmin, portanto, não é necessário adicionar permissões extras.