Завершить задание, если оно не выполнено на первичной реплике
В этом случае для каждого задания на обоих серверах требуется один из следующих двух фрагментов кода в шаге 1:
Проверка по имени группы:
IF master.dbo.svf_AgReplicaState('my_group_name')=0
raiserror ('This is not the primary replica.',2,1)
Проверка по имени базы данных:
IF master.dbo.svf_AgReplicaState('my_db_name')=0
raiserror ('This is not the primary replica.',2,1)
Если вы используете этот второй, будьте осторожны с системными базами данных, хотя - по определению они не могут быть частью какой-либо группы доступности, поэтому для них это всегда будет неудачей.
Оба из них работают из коробки для пользователей-администраторов. Для пользователей без прав администратора вы должны добавить дополнительные разрешения, одно из которых предлагается здесь :
GRANT VIEW SERVER STATE TO [user];
GRANT VIEW ANY DEFINITION TO [user];
Если на этом первом шаге для действия при сбое установить « Завершение отчета об успешном выполнении задания», журнал заданий не будет заполнен страшными знаками красного креста, а вместо основного задания они превратятся в желтые предупреждающие знаки.
По нашему опыту, это не идеально. Сначала мы применили этот подход, но быстро потеряли контроль над поиском заданий, в которых действительно возникла проблема, поскольку все задания вторичной реплики загромождали журнал заданий предупреждающими сообщениями.
То, что мы тогда пошли на это:
Работа прокси
Если вы примете эту концепцию, вам фактически потребуется создать две работы для каждой задачи, которую вы хотите выполнить. Первый - это «прокси-задание», которое проверяет, выполняется ли оно на первичной реплике. Если это так, он запускает «рабочее задание», если нет, он просто грациозно завершается, не загромождая журнал предупреждениями или сообщениями об ошибках.
Хотя мне лично не нравится идея иметь по два задания на задачу на каждом сервере, я думаю, что она определенно более удобна в обслуживании, и вам не нужно настраивать действие сбоя на шаге « Завершить успешное создание отчетов» , что немного неловко.
Для рабочих мест мы приняли схему именования. Работа прокси просто называется {put jobname here}
. Рабочая работа называется {put jobname here} worker
. Это позволяет автоматизировать запуск рабочего задания с прокси-сервера. Для этого я добавил следующую процедуру в обе основные базы данных:
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
При этом используется svf_AgReplicaState
функция, показанная выше, вы можете легко изменить это, чтобы проверить, используя вместо этого имя базы данных, вызвав другую функцию.
В рамках единственного шага прокси-задания вы называете это так:
exec procStartWorkerJob $(ESCAPE_NONE(JOBID)), '{my_group_name}'
Здесь используются токены, как показано здесь и здесь, чтобы получить идентификатор текущей работы. Затем процедура получает текущее имя задания из msdb, добавляет worker
к нему и запускает рабочее задание, используя sp_start_job
.
Хотя это все еще не идеально, он сохраняет журналы заданий более аккуратными и удобными для обслуживания, чем предыдущий вариант. Кроме того, вы всегда можете запустить задание прокси с пользователем sysadmin, поэтому добавление каких-либо дополнительных разрешений не требуется.