Нас попросили восстановить конкретное задание SQL 2005 из того, как оно существовало в определенное время в прошлом. У нас есть резервные копии базы данных MSDB за этот период времени, но я не могу перезаписать текущую базу данных MSDB, потому что я не хочу потерять последние изменения в других заданиях на этом сервере.
Если я восстановлю его как копию (назовите его MSDB_old или что-то в этом роде), как я могу извлечь информацию для этого единственного задания? Или мне нужно будет восстановить его через базу данных MSDB на рабочем сервере?
Нет необходимости восстанавливать на чистый сервер, вы можете восстановить его примерно так, как вы говорите (MSDB_old), и выполнить запрос, чтобы вернуть свою работу:
USE msdb_old
SELECT * FROM sysjobs
JOIN sysjobsteps ON sysjobs.job_id=sysjobsteps.job_id
WHERE sysjobs.NAME='My Lost Job'
ORDER BY sysjobsteps.step_id
Вам придется восстановить
РЕДАКТИРОВАТЬ: Вот сценарий, который должен делать это в SQL 2005 и 2008 (при условии, что ваша работа называлась «Моя потерянная работа» и вы восстановили ее в MSDB_Old)
DECLARE @JobID UNIQUEIDENTIFIER
SELECT @JobID = job_id FROM msdb_old.dbo.sysjobs WHERE NAME='My Lost Job'
INSERT msdb.dbo.sysjobs
SELECT * FROM msdb_old.dbo.sysjobs
WHERE job_id=@JobID
INSERT msdb.dbo.sysjobsteps
SELECT * FROM msdb_old.dbo.sysjobsteps
WHERE job_id=@JobID
SET IDENTITY_INSERT msdb.dbo.sysjobhistory ON
INSERT msdb.dbo.sysjobhistory
(instance_id,job_id,step_id,step_name,sql_message_id,sql_severity,
[message],run_status,run_date,run_time,run_duration,operator_id_emailed,
operator_id_netsent,operator_id_paged,retries_attempted,[server])
SELECT
instance_id,job_id,step_id,step_name,sql_message_id,sql_severity,
[message],run_status,run_date,run_time,run_duration,operator_id_emailed,
operator_id_netsent,operator_id_paged,retries_attempted,[server]
FROM msdb_old.dbo.sysjobhistory
WHERE job_id=@JobID
SET IDENTITY_INSERT msdb.dbo.sysjobhistory OFF
INSERT msdb.dbo.sysjobschedules
SELECT * FROM msdb_old.dbo.sysjobschedules
WHERE job_id=@JobID
Сценарий в общих чертах основан на вот этот в принятом ответе. Он был обновлен для SQL 2014 с обработкой исключений, атомарными транзакциями и некоторыми другими улучшениями.
-- Script for SQL 2014
DECLARE @JobID UNIQUEIDENTIFIER
declare @servername sysname
set @servername = @@SERVERNAME
SELECT @JobID = job_id
FROM msdb_old.dbo.sysjobs
WHERE name='My Lost Job'
BEGIN TRAN
BEGIN TRY
INSERT msdb.dbo.sysjobs
SELECT * FROM msdb_old.dbo.sysjobs
WHERE job_id=@JobID
INSERT msdb.dbo.sysjobsteps
SELECT * FROM msdb_old.dbo.sysjobsteps
WHERE job_id=@JobID
SET IDENTITY_INSERT msdb.dbo.sysjobhistory ON
INSERT msdb.dbo.sysjobhistory
(instance_id,job_id,step_id,step_name,sql_message_id,sql_severity,
[message],run_status,run_date,run_time,run_duration,operator_id_emailed,
operator_id_netsent,operator_id_paged,retries_attempted,[server])
SELECT
instance_id,job_id,step_id,step_name,sql_message_id,sql_severity,
[message],run_status,run_date,run_time,run_duration,operator_id_emailed,
operator_id_netsent,operator_id_paged,retries_attempted,[server]
FROM msdb_old.dbo.sysjobhistory
WHERE job_id=@JobID
SET IDENTITY_INSERT msdb.dbo.sysjobhistory OFF
-- New insert in sysschedules
SET IDENTITY_INSERT msdb.dbo.sysschedules ON
INSERT msdb.dbo.sysschedules (schedule_id, schedule_uid,
originating_server_id, name, owner_sid, enabled,
freq_type,freq_interval, freq_subday_type,
freq_subday_interval, freq_relative_interval,
freq_recurrence_factor, active_start_date,
active_end_date, active_start_time, active_end_time,
date_created, date_modified, version_number)
SELECT schedule_id, schedule_uid, originating_server_id, name,
owner_sid, enabled, freq_type, freq_interval, freq_subday_type,
freq_subday_interval, freq_relative_interval,
freq_recurrence_factor, active_start_date, active_end_date,
active_start_time, active_end_time, date_created, date_modified,
version_number
FROM msdb_old.dbo.sysschedules a
WHERE schedule_id = (select schedule_id from msdb_old.dbo.sysjobschedules b where job_id=@JobID )
SET IDENTITY_INSERT msdb.dbo.sysschedules OFF
INSERT msdb.dbo.sysjobschedules
SELECT * FROM msdb_old.dbo.sysjobschedules
WHERE job_id=@JobID
-- Alter job as local job
EXEC msdb.dbo.sp_add_jobserver @job_id=@JobID, @server_name = @servername
END TRY
BEGIN CATCH
SELECT
ERROR_NUMBER() AS ErrorNumber,
ERROR_SEVERITY() AS ErrorSeverity,
ERROR_STATE() AS ErrorState,
ERROR_PROCEDURE() AS ErrorProcedure,
ERROR_LINE() AS ErrorLine,
ERROR_MESSAGE() AS ErrorMessage;
ROLLBACK TRAN
RETURN
END CATCH
COMMIT TRAN
Самый простой способ извлечь отдельное задание из MSDB - щелкнуть его правой кнопкой мыши в SSMS и сказать «Задание сценария», а затем передать сценарий на целевой сервер и запустить его, чтобы воссоздать задание (возможно, с некоторыми изменениями).
Это работает только в том случае, если msdb восстанавливается как msdb - это означает, что в вашем случае вам придется восстанавливать резервную копию как msdb на рабочем сервере.
Я предполагаю, что вы можете восстановить его как копию msdb, а затем вручную извлечь все из различных таблиц msdb_copy.dbo.sysjobs / sysjobsteps / sysjobschedules / sysjobservers с помощью соединения.
Надеюсь это поможет!
Привет, хочу дополнить ответ Сквиллмана. Тестировал в 2008 R2.
Во-первых, исправив ошибку с нарушением FK с sysjobschedules и sysschedules.
Во-вторых, запустив dbo.sp_add_jobserver.
Наконец, заставив его пройти через все задания в msdb_old.dbo.sysjobs для полной репликации.
DECLARE @JobID UNIQUEIDENTIFIER
declare @jobname nvarchar(128)
DECLARE MY_CURSOR CURSOR
LOCAL STATIC READ_ONLY FORWARD_ONLY
FOR
SELECT DISTINCT job_id
FROM msdb_old.dbo.sysjobs
OPEN MY_CURSOR
FETCH NEXT FROM MY_CURSOR INTO @JobID
WHILE @@FETCH_STATUS = 0
BEGIN
SELECT @jobname = name FROM msdb_old.dbo.sysjobs WHERE job_id=@jobid
print @jobname
print 'insert in sysjobs'
INSERT msdb.dbo.sysjobs
SELECT * FROM msdb_old.dbo.sysjobs
WHERE job_id=@JobID
print 'insert in sysjobsteps'
INSERT msdb.dbo.sysjobsteps
SELECT * FROM msdb_old.dbo.sysjobsteps
WHERE job_id=@JobID
print 'insert in sysjobhistory'
SET IDENTITY_INSERT msdb.dbo.sysjobhistory ON
INSERT msdb.dbo.sysjobhistory
(instance_id,job_id,step_id,step_name,sql_message_id,sql_severity,
[message],run_status,run_date,run_time,run_duration,operator_id_emailed,
operator_id_netsent,operator_id_paged,retries_attempted,[server])
SELECT
instance_id,job_id,step_id,step_name,sql_message_id,sql_severity,
[message],run_status,run_date,run_time,run_duration,operator_id_emailed,
operator_id_netsent,operator_id_paged,retries_attempted,[server]
FROM msdb_old.dbo.sysjobhistory
WHERE job_id=@JobID
SET IDENTITY_INSERT msdb.dbo.sysjobhistory OFF
print 'insert in sysschedules'
SET IDENTITY_INSERT msdb.dbo.sysschedules ON
INSERT msdb.dbo.sysschedules
( [schedule_id]
,[schedule_uid]
,[originating_server_id]
,[name]
,[owner_sid]
,[enabled]
,[freq_type]
,[freq_interval]
,[freq_subday_type]
,[freq_subday_interval]
,[freq_relative_interval]
,[freq_recurrence_factor]
,[active_start_date]
,[active_end_date]
,[active_start_time]
,[active_end_time]
,[date_created]
,[date_modified]
,[version_number])
SELECT s.[schedule_id]
,s.[schedule_uid]
,s.[originating_server_id]
,s.[name]
,s.[owner_sid]
,s.[enabled]
,s.[freq_type]
,s.[freq_interval]
,s.[freq_subday_type]
,s.[freq_subday_interval]
,s.[freq_relative_interval]
,s.[freq_recurrence_factor]
,s.[active_start_date]
,s.[active_end_date]
,s.[active_start_time]
,s.[active_end_time]
,s.[date_created]
,s.[date_modified]
,s.[version_number]
FROM msdb_old.dbo.sysschedules s, msdb_old.dbo.sysjobschedules j
WHERE j.job_id=@JobID and s.schedule_id = j.schedule_id
SET IDENTITY_INSERT msdb.dbo.sysschedules OFF
print 'insert in sysjobschedules'
INSERT msdb.dbo.sysjobschedules
SELECT * FROM msdb_old.dbo.sysjobschedules
WHERE job_id=@JobID
print'exec adds job in server'
use msdb
EXEC dbo.sp_add_jobserver @job_id = @jobid
FETCH NEXT FROM MY_CURSOR INTO @JobID
END
CLOSE MY_CURSOR
DEALLOCATE MY_CURSOR
просто восстановите на любой сервер с новым именем, я делал это много раз раньше ...