* 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