К числу средств, которыми агент SQL Server Agent дополняет систему SQL Server, относится модуль планирования (управляющая программа или бот). Этот модуль можно использовать для планирования выполнения различных задач. Практически есть основания говорить о целом ряде разного рода заданий, которые могут выполняться на данном экземпляре SQL Server (с использованием средств SQL Server Agent, обеспечивающих планирование заданий).

Задания по обслуживанию

Когда речь заходит о заданиях, выполняемых на серверах SQL Server — или с использованием агента SQL Server Agent, — вспоминаются в первую очередь задания по обслуживанию, которые связаны с решением таких задач, как получение резервных копий, выявление несогласованностей, обслуживание индексов, обновление статистических данных, очистка истории, проверка дисков на наличие свободного пространства и т.д. Если говорить о широте охвата, то некоторые из указанных типов заданий связаны прежде всего с выполнением задач, которые я обычно отношу к уровню серверов (хотя, возможно, теоретически точнее было бы определять их как задания уровня экземпляра). Это связано с тем, что такие задания предполагают в первую очередь оценку либо обслуживание ресурсов уровня сервера (я говорю о таких заданиях, как проверка дискового пространства, очистка журналов либо очистка истории SQL Server Agent), или с тем, что они выполняются применительно к практически всем базам данных, размещенным на том или ином сервере или экземпляре. Это происходит при выполнении обслуживания индексов, снятии резервных копий или при выявлении ошибок, связанных с повреждением каких-либо компонентов.

Пакетные задания

Однако существует еще один тип часто размещаемых заданий SQL Server Agent — в рамках данной серии статей я буду называть их пакетными заданиями. Теоретически очень многие задания SQL Server Agent (хотя и не все) являются пакетными заданиями, в том смысле, что они представляют собой усеченные пакеты команд или операций, направляемые в для выполнения на соответствующем сервере. Хотя в данном случае я использую термин «пакетные задания» для обозначения блоков определяемого пользователем кода, который выполняется в базах данных для решения различных задач предприятия и для выполнения других операций. Возьмем, к примеру, приложения для электронной торговли. По моим наблюдениям, многие организации регулярно генерируют задачи по удалению невостребованных «корзин покупок», куда покупатели складывают отобранный товар, или «тележек», с которыми не проводилось никаких манипуляций на протяжении последних N часов. Подобные ситуации разрешаются довольно просто с помощью заданий SQL Server Agent, причем наилучшее решение достигается, когда задание SQL Server Agent используется для вызова хранимой процедуры или другого элемента внутри целевой базы данных.

Но нам важно понять, что же происходит с упомянутыми пакетными заданиями, когда требуется выполнить их применительно к пользовательской базе данных, входящей в состав группы доступности AlwaysOn. Если, например, мы ведем речь о фрагменте кода, который удалит или заархивирует «корзины» для товаров, укомплектованные более чем N часов назад, упомянутый код нельзя будет успешно применить к AlwaysOn Availability Replica, которая предназначена только для чтения или исключает возможность чтения либо записи. С другой стороны, этот фрагмент кода может функционировать лишь тогда, когда он корректно выполняется применительно к основной реплике, в отношении которой допускаются операции чтения/записи. Так что настоящая серия статей во многом посвящена тому, как выявить нужную реплику и перенаправить ее в ситуациях, когда встает вопрос об аварийном переключении (то есть о способности основной реплики переместиться на другой хост).

Несмотря на то, что само понятие пакетного задания автоматически предполагает выполнение кода на языке T-SQL, я настоятельно рекомендую ни в коем случае не вводить в текстовое поле Command модуля Job Step ничего кроме вызовов хранимых процедур. Потому что, во-первых, в процессе ввода символов в текстовое поле очень легко допустить ошибку, а во-вторых, обслуживание этого кода может оказаться делом весьма хлопотным.

Несмотря на то, что сотрудники организаций довольно часто используют пакетные задания для выполнения стандартных, повторяющихся операций по обработке бизнес-логики, некоторые специалисты возражают против размещения в базах данных любых элементов кода бизнес-логики. Сторонники такой позиции считают создание демона или бота на уровне приложения более эффективным решением. Я не вполне разделяю эту точку зрения. Могу посоветовать следующее. Попробуйте применить решение, наиболее подходящее в отношении длительной перспективы (SQL Server Agent или задания chron, выполняемые на уровне приложения). Хотя здесь стоит отметить, что формирование планировщиков и служб на уровне приложения — задача отнюдь не простая и что SQL Server Agent — просто потрясающий модуль для заданий, ибо он обладает гибкостью в том, что касается выполнения функций планирования и предупреждения о наличии проблем.

Что ожидает читателя

Принимая во внимание описанное выше различие между двумя типами заданий, я должен сказать, что в данной серии статей, посвященных заданиям SQL Server Agent Jobs и группам доступности AlwaysOn, основной акцент будет сделан, как это ни парадоксально, на трех различных типах заданий:

  • Задания уровня Экземпляр/Сервер, или задания, которые должны, по сути дела, выполняться на уровне сервер/экземпляр. Это задания по выявлению ошибок, связанных с повреждением каких-либо компонентов, выявлению свободного дискового пространства, по очистке истории и очистке журнала, а также задания по обработке индексов и поддержанию статистических данных.
  • Задания уровня групп доступности. В сущности, это пакетные задания, но особого рода. Они должны быть нацелены на базы данных, входящие в состав группы доступности AlwaysOn. И хотя вполне возможно существование пакетных заданий, которые нацелены на базы данных, не входящие в состав группы доступности, в данной серии статей такие пакетные задания не рассматриваются.
  • Резервные копии. Если судить по области охвата, имеется множество оснований отнести операции резервного копирования к категории заданий уровня экземпляра/сервера. Но стоит лишь учесть такой фактор, как группы доступности AlwaysOn, — и конкретные проблемы, связанные с тем, как фактически выполняются задания резервного копирования, предстают в совершенно ином свете. Как таковые, операции резервного копирования будут не просто рассматриваться в контексте настоящей серии статей как третий тип заданий. Им будет посвящен целый раздел, так как резервные копии не всегда выполняются исключительно из заданий агента SQL Server Agent, а некоторые аспекты резервного копирования шире по области охвата, чем сама идея заданий.

Синхронизация деталей на уровне сервера

В процессе установки решений, обеспечивающих высокую доступность (high availability, HA) или HA + восстановление после аварийного сбоя (disaster recovery, DR) администратор всегда должен помнить о том, что базовым компонентом механизма обеспечения отказоустойчивости при выполнении данного сценария является группа доступности (или группа определенных пользователем баз данных). Избыточность или синхронизация обычно обрабатываемых на уровне сервера (или экземпляра) параметров не обеспечивается с помощью групп доступности AlwaysOn. И, как это ни прискорбно, даже в изобилующих иными подробностями «белых» книгах, электронных книгах Books Online и других выпускаемых Microsoft ресурсах, посвященных установке групп доступности AlwaysOn, как правило, об этом говорится очень мало.

Проблемы синхронизации

Поскольку базовая цель создания средств обеспечения высокой доступности и восстановления после аварийного сбоя состоит в обеспечении избыточности с идеей упреждающего решения проблем сбоев, логично предположить, что обеспечение избыточности данных представляет собой необходимое, но не достаточное условие достижения этой цели. Чтобы добиться избыточности всего устройства хранения, специалистам организаций необходимо сделать избыточными дополнительные детали уровня сервера (или уровня экземпляра), в том числе:

  • Учетные имена. Учетные имена группируются на уровне сервера/экземпляра, тогда как пользователи группируются на уровне базы данных — и это обстоятельство является источником постоянных недоразумений для администраторов, не имеющих опыта работы с SQL Server. И даже понимание ситуации всеми администраторами не сможет отменить необходимости синхронизации учетных имен (и их привязки к соответствующим пользователям) на всех серверах, где будет располагаться группа доступности. К счастью, однако, в версии SQL Server 2012 заложены элементы подхода к переводу аутентификации внутрь базы данных с использованием идеи автономных баз данных (Contained Databases). Соответственно, наиболее эффективный подход к работе с группами доступности AlwaysOn состоит в том, чтобы обеспечивать переносимость пользователей с применением идеи автономного пользователя. Надо отметить, однако, что хотя обеспечение автономности является замечательным достижением (или станет таковым, когда/если мы получим от Microsoft более продвинутый набор инструментов), следует иметь в виду, что средства автономизации могут стать источником проблем, касающихся взаимодействия между пользовательскими базами данных и tempdb. Так что не забудьте непременно протестировать эти функции в полном объеме, перед тем как размещать автономных пользователей в рабочей сети.
  • Связанные серверы. В случаях, когда необходимо обеспечивать взаимодействие между SQL Server и удаленным сервером, самый безопасный вариант — установить такое взаимодействие через связанные серверы (или явным образом заданные удаленные конечные системы) и не допускать выполнения нерегламентированных распределенных запросов, что было бы чистым безумием. Следовательно, если нужно обеспечить обмен данными между базами данных группы доступности с более старой системой AS/400 или с другим экземпляром SQL Server либо с базами данных Oracle, вам придется определить эти детали связанных серверов на всех хостах, участвующих в ваших группах доступности — иначе при аварийном переключении с основной реплики произойдет сбой в процессе коммуникации.
  • Конечные системы. При использовании брокера службы или иных усовершенствованных компонентов последние тоже должны быть подготовлены.
  • Пулы ресурсов. Мне доводилось работать как с регулятором ресурсов SQL Server, так и с группами доступности AlwaysOn SQL Server, но в моей практике не было случая, когда оба компонента применяются одновременно. Если вы намереваетесь совместно использовать оба компонента для создания обеспечивающих высокую доступность решений, где соглашения об уровне обслуживания выполняются путем сдерживания тех или иных процессов, вам следует также проследить за тем, чтобы пулы ресурсов и определения, которые вы создаете на основном сервере, синхронизировались с другими серверами в вашей топологии.
  • Оповещения. Мой опыт свидетельствует о том, что реализованная в агенте SQL Server функция оповещения используется недостаточно, но если в организации нужно наладить систему упреждающих оповещений о потенциальных проблемах с SQL Server или оповещений о ситуациях, когда выполняется аварийное переключение внутри группы доступности, специалистам такой организации придется позаботиться и об обеспечении синхронизации оповещений на всех серверах, входящих в топологию группы доступности. Эту проблему я буду рассматривать подробнее в следующей статье.
  • Задания агентов SQL Server. Как уже отмечалось ранее при обсуждении определения пакетных заданий, существует множество различных типов заданий, которые нужно синхронизировать — а возможно, и модифицировать, — чтобы обеспечить их корректное выполнение в ситуациях, когда в сети реализованы группы доступности AlwaysOn и когда пользовательские базы данных могут перемещаться с одного сервера на другой.
  • Резервное копирование в SQL Server. Концепции процедур резервного копирования аналогичны концепциям заданий, и в условиях, когда базы данных могут перемещаться от одного хоста к другому, они тоже нуждаются в дополнительной подстройке, а также требуют учета дополнительных обстоятельств.

Если синхронизация не обеспечена

Первоначальная синхронизация практически всех деталей, описанная выше, — процедура почти тривиальная. В большинстве случаев вам нужно только включить объекты в сценарий и выполнить эти определения на других серверах. Задания и процедуры резервного копирования чуть сложнее. Здесь в конечном итоге администратор имеет дело с понятием целевого объекта.

Загвоздка, разумеется, в том, что если с самого начала какая-то задача была оформлена в виде сценария и изначально какие-то параметры были синхронизированы, это отнюдь не означает, что согласованность будет сохраняться и дальше. И в этом, кстати, состоит одна из проблем, рассматриваемых в данной серии статей: если не обеспечено выполнение синхронизации или система не извещает вас о случаях рассогласования компонентов, аварийный перевод группы доступности с одного хоста на другой может успешно завершаться на уровне данных, но способен привести к сбою по причине отсутствия компонентов либо зависимостей на новом сервере.