3.5. SQL Server Agent - Часть 2

3.5.4. Запуск работы

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

sp_apply_job_to_targets [ @job_id = ] job_id | 
    [ @job_name = ] 'job_name' 
    [ , [ @target_server_groups = ] 'target_server_groups' ] 
    [ , [ @target_servers = ] 'target_servers' ] 
    [ , [ @operation = ] 'operation' ]
  • @job_id и @job_name – позволяют с помощью идентификатора или имени работы соответственно указать работу, которую мы хотим привязать к серверу;
  • @target_server_groups – строка из имен групп серверов, разделенных запятыми, к которым нужно произвести привязку;
  • @target_servers – строка из имен серверов, разделенных запятыми, к которым нужно произвести привязку;
  • @operation – операция, которую необходимо выполнить. В данном параметре можно указать одно из следующих значений:
    • APPLY – необходимо привязать работу к указанным серверам;
    • REMOVE – необходимо удалить привязку работы от указанных серверов.

Посмотрим пример связывания работы с сервером:

EXEC sp_apply_job_to_targets 
  @job_name = 'Тестовая работа 2',
  @target_servers='NOTEBOOK', 
  @operation=APPLY

В параметре @target_servers указано имя NOTEBOOK. Это имя моего компьютера и соответственно имя установленного экземпляра SQL Server по умолчанию, на котором я и пишу примеры для данной книге. Ваш экземпляр сервера скорей всего будет называться по-другому, поэтому укажите его имя.

Если вы используете именованный экземпляр MS SQL Server, то необходимо указать имя полностью. Например, ваш экземпляр может называться 'Econom' и находиться на сервере 'BigServer'. В этом случае, в параметре @target_servers необходимо указать строку 'BigServer\Econom'.

В параметре @operation указано значение APPLY, то есть указанный сервер должен быть назначен работе.

Вот теперь мы готовы запускать работу на выполнение. Существует две возможности сделать это: автоматически с помощью планировщика и вручную. Сейчас нам предстоит рассмотреть ручной метод, потому что автоматический – это отдельный разговор.

Для ручного запуска работы на выполнение используется хранимая процедура sp_start_job, которая в общем виде выглядит следующим образом:

sp_start_job [@job_name =] 'job_name' | [@job_id =] job_id
    [,[@error_flag =] error_flag]
    [,[@server_name =] 'server_name']
    [,[@step_name =] 'step_name']
    [,[@output_flag =] output_flag]

Давайте рассмотрим параметры этой команды:

  • @job_id и @job_name – позволяют с помощью идентификатора или имени работы соответственно указать работу, которую мы хотим выполнить;
  • @error_flag – зарезервировано;
  • @server_name – имя сервера, на котором нужно запустить работу. Данное имя должно быть связано с работой с помощью системной процедуры sp_apply_job_to_targets;
  • @step_name – имя шага, начиная с которого нужно начать выполнение. Если ничего не задано, то работа будет запущена с самого первого шага. Иногда бывает необходимо запустить работу не с первого шага. Например, в разделе 3.5.4 мы создали два шага удаления и создания таблицы. Если вы уверены, что создаваемой таблицы нет, то первый шаг можно пропустить.
  • @output_flag – зарезервировано.

Минимальная команда запуска работы на выполнение будет выглядеть следующим образом:

EXEC sp_start_job @job_name = 'Тестовая работа 2'

Если в разделе 3.5.4. вы создавали все шаги, которые мы рассматривали, то можете просмотреть таблицу tbPeoples и убедиться, что в нее вставлена новая строка, где поле имени равно имени компьютера, а фамилия равна номеру шага.

Если работа связана с несколькими серверами, то для запуска на конкретном сервере используем параметр @server_name. Следующий пример запускает работу на сервере NOTEBOOK, начиная со второго шага, который имеет имя 'Удаляем таблицу':

EXEC sp_start_job @job_name = 'Тестовая работа 2', 
    @server_name = 'notebook',
    @step_name = 'Удаляем таблицу'

Теперь создадим файл text.txt на диске С: и выполним команду начиная со второго шага, где запускается системная команда:

EXEC sp_start_job @job_name = 'Тестовая работа 2', 
    @step_name = 'Системная команда'

Убедитесь, что созданный файл удален.

3.5.5. Информация о работе

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

Для просмотра информации о работе используется хранимая процедура sp_help_job, которая выглядит следующим образом:

sp_help_job [ [ @job_id = ] job_id ] 
    [ , [ @job_name = ] 'job_name' ] 
    [ , [ @job_aspect = ] 'job_aspect' ] 
    [ , [ @job_type = ] 'job_type' ] 
    [ , [ @owner_login_name = ] 'login_name' ] 
    [ , [ @subsystem = ] 'subsystem' ] 
    [ , [ @category_name = ] 'category' ] 
    [ , [ @enabled = ] enabled ] 
    [ , [ @execution_status = ] status ] 
    [ , [ @date_comparator = ] 'date_comparison' ] 
    [ , [ @date_created = ] date_created ] 
    [ , [ @date_last_modified = ] date_modified ] 
    [ , [ @description = ] 'description_pattern' ]

Давайте рассмотрим параметры этой команды:

  • @job_id и @job_name – позволяют с помощью идентификатора или имени работы соответственно указать работу, информация о которой нас интересует;
  • @job_aspect – атрибуты работы, которые необходимо отобразить. В этом параметре можно указывать одно из следующих значений:
    • ALL – полную информацию (значение по умолчанию);
    • JOB – информацию о работе;
    • STEPS – информация о шагах;
    • SCHEDULES – информация о плане выполнения;
    • TARGET – информация о серверах, к которым привязана работа.
  • @job_type – тип работы, включаемый в отчет. В этом параметре можно указать одно из следующих значений:
    • LOCAL – локальный, т.е. привязанный к текущему серверу;
    • MULTISERVER – привязанный к нескольким серверам.
  • @owner_login_name – имя пользователя, владельца работы;
  • @subsystem – отобразить работы, которые выполняют указанные в этом параметре системы команд;
    • ACTIVESCRIPTING –активный сценарий;
    • CMDEXEC – команда ОС;
    • DISTRIBUTION –дистрибутор репликации;
    • SNAPSHOT – агент репликации снятия снимка;
    • LOGREADER – агента чтения журнала;
    • MERGE – агента репликации смешивания (Merge);
    • TSQL – Transact-SQL.
  • @category_name – имя категории;
  • @enabled – если параметр равен 1, то информация должна отображаться для активных работ, иначе для не активных;
  • @execution_status – отобразить работы с указанным статусом. В этом параметре можно указать одно из следующих значений:
    • 0 – отобразить работы, которые находятся в состоянии ожидании или приостановленные;
    • 1 – выполняющиеся работы;
    • 2 – ожидающие потока;
    • 3 – попытка повторить шаг;
    • 4 – ожидании;
    • 5 – приостановленный;
    • 7 – выполняющий завершающее действие.
  • @date_comparator – оператор сравнения, который будет использоваться для сравнения дат из параметров @date_created и @date_last_modified. Здесь можно указывать знаки равенства, больше или меньше;
  • @date_created – дата создания;
  • @date_last_modified – дата последнего изменения;
  • @description – описание.

Если выполнить процедуру без параметров, то она отобразит на экране все доступные на сервере работы:

EXEC sp_help_job

Следующая команда позволяет увидеть работы, которые выполняют Transact-SQL запросы:

EXEC sp_help_job @subsystem='TSQL'

Следующий пример показывает, как увидеть работы, созданные после 1-го января 2005-го года:

EXEC sp_help_job 
    @date_comparator = '>',
    @date_created='01.01.2005' 

В параметре @date_created указываем необходимую дату, а в параметре @date_comparator символ сравнения. Если изменить знак сравнения на знак равенства, то мы увидим работы, созданные именно 1-го января 2005-го года:

EXEC sp_help_job @date_comparator = '=',
    @date_created='01.01.2005' 

Минимальная команда отображения информации о работе будет выглядеть следующим образом:

EXEC sp_help_job @job_name='Тестовая работа 2'

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

EXEC sp_help_job @job_name='Тестовая работа 2',
    @job_aspect='STEPS'

В результате мы получим таблицу шагов, в которой столбцы идентичны именам параметров процедуры создания шагов sp_add_jobstep. Строки отсортированы по полю step_id, т.е. отображаются в том же порядке, в котором они должны выполняться сервером.

Для получения информации о шаге работы, есть процедура sp_help_jobstep, которая выгладит следующим образом:

sp_help_jobstep [ @job_id = ] 'job_id' | 
    [ @job_name = ] 'job_name' 
    [ , [ @step_id = ] step_id ] 
    [ , [ @step_name = ] 'step_name' ] 
    [ , [ @suffix = ] suffix ]

Рассмотрим параметры этой процедуры:

  • @job_id и @job_name – позволяют с помощью идентификатора или имени работы соответственно указать работу, информация, о шагах которой нас интересует;
  • @step_id – идентификатор шага, информация о котором нас интересует;
  • @step_name – имя интересующего вас шага;
  • @suffix – если параметр равен 1, то в поле "flag" будет добавлено описание.

Простейший способ узнать информацию о шагах работы, выполнить процедуру sp_help_jobstep, указав ей только имя интересующей вас работы:

USE msdb
EXEC sp_help_jobstep @job_name='Тестовая работа 2'

Результат работы идентичен выполнению процедуры sp_help_job с указанием этого же имени работы и параметра @job_aspect со значением STEPS:

EXEC sp_help_job 
    @job_name='Тестовая работа 2',
    @job_aspect='STEPS'

Следующий пример отображает информацию о первом шаге работы:

EXEC sp_help_jobstep @job_name='Тестовая работа 2',
  @step_id='1'

3.5.6. Управление работами

Все в нашем мире изменятся и только исторические ценности должны оставаться в своем первоначальном виде. Код SQL запросов к историческим ценностям отнести трудно, поэтому нередко приходиться вносить в код изменения, улучшения или корректировку в соответствии с изменяющимися потребностями задачи, а как показывает практика, даже простая задача может изменяться.

Для изменения работы используется процедура sp_update_job, которая выглядит следующим образом:

sp_update_job [@job_id =] job_id | [@job_name =] 'job_name'
    [, [@new_name =] 'new_name'] 
    [, [@enabled =] enabled]
    [, [@description =] 'description'] 
    [, [@start_step_id =] step_id]
    [, [@category_name =] 'category'] 
    [, [@owner_login_name =] 'login']
    [, [@notify_level_eventlog =] eventlog_level]
    [, [@notify_level_email =] email_level]
    [, [@notify_level_netsend =] netsend_level]
    [, [@notify_level_page =] page_level]
    [, [@notify_email_operator_name =] 'email_name']
    [, [@notify_netsend_operator_name =] 'netsend_operator']
    [, [@notify_page_operator_name =] 'page_operator']
    [, [@delete_level =] delete_level] 
    [, [@automatic_post =] automatic_post]

Даже первый взгляд показывает, что процедура очень похожа на процедуру добавления работы sp_add_job. Параметры идентичны, поэтому не будем тратить время на их рассмотрение, а лучше посмотрим, как можно использовать процедуру sp_update_job на практике.

Давайте изменим у работы "Тестовая работа 2" описание и оператора, который будет получать e-mail и NET SEND сообщения:

USE msdb
EXEC sp_update_job 
   @job_name = 'Тестовая работа 2', 
   @description = 'Тестовая работа',
   @notify_email_operator_name = 'Михаил',
   @notify_netsend_operator_name = 'Михаил'

Для удаления работы используется процедура sp_delete_job, которой в качестве параметра нужно указать идентификатор или имя удаляемой работы. Например, следующая команда удалит, созданную в разделе 3.5.1 работу с именем Тестовая работа:

EXEC sp_delete_job @job_name = 'Тестовая работа'

3.5.7. Управление шагами

Для обновления шагов работы используется хранимая процедура sp_update_jobstep. Она выгладит следующим образом:

sp_update_jobstep [@job_id =] job_id, | [@job_name =] 'job_name', 
    [@step_id =] step_id 
    [, [@step_name =] 'step_name']
    [, [@subsystem =] 'subsystem'] 
    [, [@command =] 'command']
    [, [@additional_parameters =] 'parameters']
    [, [@cmdexec_success_code =] success_code]
    [, [@on_success_action =] success_action] 
    [, [@on_success_step_id =] success_step_id]
    [, [@on_fail_action =] fail_action] 
    [, [@on_fail_step_id =] fail_step_id]
    [, [@server =] 'server'] 
    [, [@database_name =] 'database']
    [, [@database_user_name =] 'user'] 
    [, [@retry_attempts =] retry_attempts]
    [, [@retry_interval =] retry_interval] 
    [, [@os_run_priority =] run_priority]
    [, [@output_file_name =] 'file_name'] 
    [, [@flags =] flags]

Параметры у процедуры обновления такие же, как и при добавлении. С помощью параметров @job_id или @job_name процедура определяет работу, которую нужно изменить, а с помощью параметра @step_id задается номер изменяемого шага.

Давайте изменим второй шаг нашей работы, где мы выполняем системную команду удаления файла на копирование файла в директорию c:\backup. При этом, имя файла, в который будет происходить копирование должно состоять из текущей даты и расширения txt:

EXEC sp_update_jobstep 
   @job_name = 'Тестовая работа 2',
   @step_id=2,
   @step_name = 'Команда копирования',
   @subsystem = 'CMDEXEC',
   @command = 'copy c:\text.txt c:\backup\[DATE].txt',

Изменяются только указанные в процедуре sp_update_jobstep параметры. Все остальные остаются без изменений, а не обнуляются.

Для удаления шага работы используется процедура sp_delete_jobstep, которая выглядит следующим образом:

sp_delete_jobstep [ @job_id = ] job_id , | 
    [ @job_name = ] 'job_name' , 
    [ @step_id = ] step_id

С помощью параметров @job_id или @job_name процедура определяет работу, в которой нужно удалить шаг, а с помощью параметра @step_id задается номер удаляемого шага.

Следующий пример удаляет шаг 2, который выполняет системную команду:

EXEC sp_delete_jobstep 
   @job_name = 'Тестовая работа 2',
   @step_id=2

Выполните следующую команду, чтобы убедиться, что шаг удален:

EXEC sp_help_job 
    @job_name='Тестовая работа 2',
    @job_aspect='STEPS'

Обратите внимание, что идентификаторы автоматически перестроены. Теперь под номером 2 находится шаг, который был до удаления под номером 3.

3.5.8. Эффективное использование работ

Работы достаточно эффективное средство для решения большинства нудных работ администратора и при этом мощь не имеет границ. Но далеко не все используют работы хотя бы на 50% возможностей. Большинство администраторов ограничивается созданием с помощью планировщика системы резервного копирования базы данных, в крайнем случае, реализуют еще пару простых задач. При этом используется простейшая логика, а ведь существующие средства позволяют реализовать достаточно сложную логику.

Давайте вспомним параметры, которые есть у шагов работы. Наиболее интересными являются: @on_success_action, @on_success_step_id, @on_fail_action и @on_fail_step_id. С их помощью можно построить логику выполнения достаточно сложной работы. Например, у вас есть работа, выполняющая резервное копирование. В конце рабочего дня создается полная резервная копия базы, а в течение дня выполняется резервирование изменений (дифференцированное копирование или резервирование журнала). Более подробно о резервировании мы поговорим в разделе 4.10, а пока ограничимся общими понятиями.

Большинство будет создавать работу резервирования полной копии, состоящую из одного шага, ведь для решения задачи необходима только одна команда. А что, если данные разрушены, и сделать полную резервную копию нельзя? Работа завершиться ошибкой и придется вызывать администратора для решения проблемы. Но можно поступить более эффективно и выполнить следующее:

  • Первый шаг работы пытается создать полную резервную копию со следующими параметрами:
    • В параметре @on_success_action указываем значение 1, то есть удачное завершение работы;
    • в параметре @on_fail_action устанавливаем значение 3, то есть в случае ошибки переходим на следующий шаг.
  • Второй шаг будет выполняться, если на первом произошла ошибка. Раз данные нарушены, пока администратор разбирается с проблемой можно автоматически запустить резервирование изменений.

Администратор, узнав об ошибке, начнет восстанавливать данные и для этого у него уже будет все готово, а именно: полная резервная копия за вчерашний день и все копии изменений за день, когда прошла ошибка. Администратору достаточно восстановить все резервные копии и база данных будет готова к работе в максимально короткий срок.

Данный пример выбран не случайно, потому что он интересует любого специалиста, который встречался с разрушением данных. Руководство всегда требует от нас, чтобы база данных была доступна всегда и не понимает никаких поломок, потому что в информационные технологии вкладываются слишком большие деньги.

Если есть возможность автоматизировать какую-либо задачу, то необходимо сделать это. Но действовать нужно аккуратно. В примере с созданием резервной копии, мы могли бы добавить в работу еще один шаг – при удачном выполнении перейти на третий шаг, где будет автоматически происходить восстановление данных, но эту операцию лучше не делать без вмешательства человека. Сначала сервер должен осмотреть специалист, убедиться, что данные действительно разрушены и требуется восстановление. В идеальном случае, администратор должен еще и определить источник ошибки.

Предыдущая глава

3.5. SQL Server Agent - Часть 1

О блоге

Программист, автор нескольких книг серии глазами хакера и просто блогер. Интересуюсь безопасностью, хотя хакером себя не считаю

Обратная связь

Без проблем вступаю в неразборчивые разговоры по e-mail. Стараюсь отвечать на письма всех читателей вне зависимости от страны проживания, вероисповедания, на русском или английском языке.

Пишите мне