Я ищу рекомендации по работе с запланированными заданиями агента SQL Server в группах доступности SQL Server 2012. Может быть, я что-то упустил, однако в текущем состоянии я чувствую, что агент SQL Server на самом деле не интегрирован с этой замечательной функцией SQL2012.
Как я могу сделать запланированное задание агента SQL осведомленным о переключении узла? Например, у меня есть задание, работающее на основном узле, который загружает данные каждый час. Теперь, если основной отказывает, как я могу активировать работу на дополнительном, который теперь становится основным?
Если я планирую задание всегда на дополнительном устройстве, оно завершается сбоем, потому что вспомогательное только для чтения.
Ответы:
В вашем задании агента SQL Server есть некоторая условная логика для проверки того, выполняет ли текущий экземпляр конкретную роль, которую вы ищете в своей группе доступности:
Все, что это делает, это извлекает текущую роль локальной реплики, и, если
PRIMARY
она входит в эту роль, вы можете делать все, что нужно вашей работе, если она является основной репликой.ELSE
Блок не является обязательным, но справиться с возможной логикой , если ваша локальная копия не является первичной.Конечно, измените
'YourAvailabilityGroupName'
в приведенном выше запросе фактическое имя группы доступности.Не путайте группы доступности с экземплярами отказоустойчивого кластера. Является ли экземпляр первичной или вторичной репликой для данной группы доступности, это не влияет на объекты уровня сервера, такие как задания агента SQL Server и т. Д.
источник
Вместо того, чтобы делать это для каждого задания (проверяя каждое задание на состояние сервера перед тем, как продолжить), я создал задание, запущенное на обоих серверах, чтобы проверить, в каком состоянии находится сервер.
Этот подход обеспечивает ряд вещей
скрипт проверяет базу данных в поле ниже
Этот процесс выполняется каждые 15 минут на каждом сервере. (имеет дополнительный бонус за добавление комментария, чтобы сообщить людям, почему работа была отключена)
Это не защищает от дурака, но для ночных нагрузок и почасовой работы он выполняет свою работу.
Даже лучше, чем запускать эту процедуру по расписанию, вместо этого запустите ее в ответ на предупреждение 1480 (предупреждение об изменении роли AG).
источник
Я знаю две концепции для достижения этой цели.
Предварительное условие: основываясь на ответе Томаса Стрингера, я создал две функции в главной базе данных наших двух серверов:
Завершить задание, если оно не выполнено на первичной реплике
В этом случае для каждого задания на обоих серверах требуется один из следующих двух фрагментов кода в шаге 1:
Проверка по имени группы:
Проверка по имени базы данных:
Если вы используете этот второй, будьте осторожны с системными базами данных, хотя - по определению они не могут быть частью какой-либо группы доступности, поэтому для них это всегда будет неудачей.
Оба из них работают из коробки для пользователей-администраторов. Для пользователей без прав администратора вы должны добавить дополнительные разрешения, одно из которых предлагается здесь :
Если на этом первом шаге для действия при сбое установить « Завершение отчета об успешном выполнении задания», журнал заданий не будет заполнен страшными знаками красного креста, а вместо основного задания они превратятся в желтые предупреждающие знаки.
По нашему опыту, это не идеально. Сначала мы применили этот подход, но быстро потеряли контроль над поиском заданий, в которых действительно возникла проблема, поскольку все задания вторичной реплики загромождали журнал заданий предупреждающими сообщениями.
То, что мы тогда пошли на это:
Работа прокси
Если вы примете эту концепцию, вам фактически потребуется создать две работы для каждой задачи, которую вы хотите выполнить. Первый - это «прокси-задание», которое проверяет, выполняется ли оно на первичной реплике. Если это так, он запускает «рабочее задание», если нет, он просто грациозно завершается, не загромождая журнал предупреждениями или сообщениями об ошибках.
Хотя мне лично не нравится идея иметь по два задания на задачу на каждом сервере, я думаю, что она определенно более удобна в обслуживании, и вам не нужно настраивать действие сбоя на шаге « Завершить успешное создание отчетов» , что немного неловко.
Для рабочих мест мы приняли схему именования. Работа прокси просто называется
{put jobname here}
. Рабочая работа называется{put jobname here} worker
. Это позволяет автоматизировать запуск рабочего задания с прокси-сервера. Для этого я добавил следующую процедуру в обе основные базы данных:При этом используется
svf_AgReplicaState
функция, показанная выше, вы можете легко изменить это, чтобы проверить, используя вместо этого имя базы данных, вызвав другую функцию.В рамках единственного шага прокси-задания вы называете это так:
Здесь используются токены, как показано здесь и здесь, чтобы получить идентификатор текущей работы. Затем процедура получает текущее имя задания из msdb, добавляет
worker
к нему и запускает рабочее задание, используяsp_start_job
.Хотя это все еще не идеально, он сохраняет журналы заданий более аккуратными и удобными для обслуживания, чем предыдущий вариант. Кроме того, вы всегда можете запустить задание прокси с пользователем sysadmin, поэтому добавление каких-либо дополнительных разрешений не требуется.
источник
Если процесс загрузки данных представляет собой простой запрос или вызов процедуры, то вы можете создать задание на обоих узлах и позволить ему определить, является ли его основным узлом на основе свойства Updateability базы данных, прежде чем он выполнит процесс загрузки данных:
источник
Всегда лучше создать новый шаг задания, который проверяет, является ли он первичной репликой, тогда все в порядке, чтобы продолжить выполнение задания, иначе, если это вторичная реплика, остановите задание. Не подведите задание, иначе оно будет отправлять ненужные уведомления. Вместо этого остановите задание, чтобы оно было отменено и уведомления не отправлялись всякий раз, когда эти задания выполняются на вторичной реплике.
Ниже приведен скрипт для добавления первого шага для конкретной работы.
Примечание для выполнения скрипта:
Если имеется несколько групп доступности, задайте имя AG в переменной @AGNameToCheck_IfMoreThanSingleAG, чтобы указать, какой AG следует проверять на наличие состояния реплики.
Также обратите внимание, что этот скрипт должен хорошо работать даже на тех серверах, у которых нет групп доступности. Будет выполняться только для версий SQL Server 2012 и выше.
источник
Другой способ - вставить шаг в каждое задание, которое должно быть выполнено первым, со следующим кодом:
Задайте этот шаг, чтобы перейти к следующему шагу в случае успеха и выйти из отчета об успешном выполнении задания при сбое.
Я считаю более понятным добавить дополнительный шаг вместо добавления дополнительной логики к существующему шагу.
источник
Другой, более новый вариант, использует master.sys.fn_hadr_is_primary_replica ('DbName'). Я обнаружил, что это очень полезно при использовании агента SQL для обслуживания базы данных (в сочетании с курсором, которым я пользовался годами), а также при выполнении ETL или другой конкретной задачи для базы данных. Преимущество заключается в том, что он выделяет базу данных, а не смотрит на всю группу доступности ... если это то, что вам нужно. Это также делает более невероятным, что команда будет выполняться для базы данных, которая «была» на первичном сервере, но, скажем, во время выполнения задания произошел автоматический переход на другой ресурс, и теперь он находится на вторичной реплике. Вышеуказанные методы, которые смотрят на первичную реплику, смотрят один раз и не обновляются. Имейте в виду, что это просто другой способ достижения очень похожих результатов и предоставления более детального контроля, если вам это нужно. Кроме того, причина, по которой этот метод не обсуждался, когда задавался этот вопрос, заключается в том, что Microsoft не выпускала эту функцию до выхода SQL 2014. Ниже приведены некоторые примеры использования этой функции:
Если вы хотите использовать это для обслуживания базы данных пользователей, это то, что я использую:
Я надеюсь, что это полезный совет!
источник
Я использую это:
источник