* originally published on our old blog in January 4, 2012
One of the little challenges a DBA has to deal with when setting up SQL Server mirroring is the handling of SQL Server jobs. SQL Server mirroring works at the database level so SQL Server instance level objects are not mirrored. To achieve a transparent fail-over some of those instance level objects, like certain SQL Jobs related to your mirrored databases, need to be somehow "mirrored" as well. The objective is simple: any relevant jobs that were running on the principal, on fail-over should start running on the mirror. So we have to make sure the jobs are kept in sync and are activated at the right moment (you don't want those jobs to be running on the mirror until the fail-over happens).
One approach would be to have scheduled jobs that periodically syncs the SQL Jobs on the principal with those on the mirror and periodically checks the mirroring status to determine if the jobs on the mirror need to be activated.
Another simpler approach would be to use multi-server jobs. You can use a third server, like the witness for example, as the job "master" and do the following:
A couple of notes to keep in mind:
One of the little challenges a DBA has to deal with when setting up SQL Server mirroring is the handling of SQL Server jobs. SQL Server mirroring works at the database level so SQL Server instance level objects are not mirrored. To achieve a transparent fail-over some of those instance level objects, like certain SQL Jobs related to your mirrored databases, need to be somehow "mirrored" as well. The objective is simple: any relevant jobs that were running on the principal, on fail-over should start running on the mirror. So we have to make sure the jobs are kept in sync and are activated at the right moment (you don't want those jobs to be running on the mirror until the fail-over happens).
One approach would be to have scheduled jobs that periodically syncs the SQL Jobs on the principal with those on the mirror and periodically checks the mirroring status to determine if the jobs on the mirror need to be activated.
Another simpler approach would be to use multi-server jobs. You can use a third server, like the witness for example, as the job "master" and do the following:
- All the jobs that must be "mirrored" should be created on the job "master" server as multi-server jobs.
- The target for those jobs is set to be the principal
- Create a job on the job master server that checks the mirror status, let's say every minute
- If a fail-over has happened and the mirror has become the principal then it changes the target server for those jobs.
CREATE PROCEDURE [dbo].[usp_ChangeJobTarget]
@DBName varchar(256) = 'MyMirroredDB',
@Principal varchar(256) = 'MyPrincipal',
@Mirror varchar(256) = 'MyMirror'
AS
BEGIN
SET NOCOUNT ON;
DECLARE @current_principal varchar(256)
DECLARE @principalID int
DECLARE @mirrorID int
DECLARE @jobname varchar(256)
SELECT @current_principal = principal_server_name FROM sys.database_mirroring_witnesses WHERE database_name = @DBName
SELECT @principalID = server_id from msdb.dbo.systargetservers WHERE server_name = @Principal
SELECT @mirrorID = server_id from msdb.dbo.systargetservers WHERE server_name = @Mirror
IF @current_principal like @Mirror
BEGIN
-- principal has changed so we need to change the target for all jobs
-- first let's get the complete list of jobs that target the principal
DECLARE @JobList TABLE
(
[JobName] [varchar](256) NOT NULL,
[Changed] bit NOT NULL
)
INSERT INTO @JobList
SELECT [name], 0
FROM msdb.dbo.sysjobs as a INNER JOIN msdb.dbo.sysjobservers as b on a.job_id = b.job_id
WHERE b.server_id = @principalID
-- now for each job on the @JobList we need to change the target from principal to mirror
SELECT TOP 1 @jobname = [JobName] FROM @JobList WHERE [Changed] = 0
WHILE (@jobname IS NOT NULL)
BEGIN
exec msdb.dbo.sp_delete_jobserver @job_name = @jobname, @server_name = @Principal
exec msdb.dbo.sp_add_jobserver @job_name = @jobname, @server_name = @Mirror
UPDATE @JobList SET [Changed] = 1 WHERE [JobName] = @jobname
SET @jobname = null
SELECT TOP 1 @jobname = [JobName] FROM @JobList WHERE [Changed] = 0
END
END
END
GO
A couple of notes to keep in mind:
- There is a small delay on replicating a multi-server job. In other words, if you change a job or add a new job on the job master server it will take up to a minute for those changes to be reflected on the target server(s).
- The above stored procedure only goes in one direction – changes the target from principal to mirror in case of fail-over. You will need to adjust it to make it work both ways – one simple way to accomplish this is to simply compare the current principal with the target for those jobs and if they don’t match then change the target.
- The above script is provided as is - use at your own risk.
0 comments:
Post a Comment