Uno de los problemas que tenemos cuando configuramos LogShipping en varios servidores o en varias bases de datos de forma simultanea, sobre todo si lo hacemos de forma manual, es que por defecto las programaciones (Schedules) de ejecución de los jobs de restauración en el servidor secundario se llaman igual (DefaultRestoreJobSchedule), y lo que es peor, se ejecutan todos a la misma hora, con la misma periodicidad, lo cuál puede llevarnos a problemas de rendimiento periódicos. En la imagen siguiente podemos ver los típicos dientes de sierra que tendríamos en el sistema de monitorización.

chart

Desde que pusimos el LS en marcha se observa como en este servidor secundario cada 5 minutos tenemos un pico de CPU. Estos picos no son muy elevados, pero en realidad este servidor no tiene carga de trabajo a excepción de mantener las bases de datos secundarias en un escenario de LogShipping, y por lo tanto, la carga debería ser mucho más baja y no debería presentar estos picos. Para modificar este comportamiento podemos hacer lo siguiente. Primero, comprobamos cuantas programaciones tienen todavía el nombre que se le asigna por defecto.

SELECT sch.name as scheduleName, sj.name as jobName, REPLACE ( sj.name, N'LSRestore', N'LSRestoreJobSchedule' ) as newName
FROM
     msdb.dbo.sysschedules sch 
        inner join msdb.dbo.sysjobschedules jsch on sch.schedule_id = jsch.schedule_id
        inner join msdb.dbo.sysjobs sj on jsch.job_id = sj.job_id
WHERE 
    sch.name like 'DefaultRestoreJobSchedule'

La consulta anterior nos devolverá un listado con los jobs cuyas programaciones cumplan la condición. Ahora, podemos modificarlos.

UPDATE msdb.dbo.sysschedules 
SET 
    name = REPLACE ( sj.name, N'LSRestore', N'LSRestoreJobSchedule' )  
FROM msdb.dbo.sysschedules sch
    inner join msdb.dbo.sysjobschedules jsch on sch.schedule_id = jsch.schedule_id
    inner join msdb.dbo.sysjobs sj on jsch.job_id = sj.job_id    
WHERE 
    sch.name like 'DefaultRestoreJobSchedule'

Podemos renombrarlos siguiendo el criterio que queramos. En nuestro caso le indicamos que el nuevo nombre de la programación sea el nombre del job cambiando el sufijo LSRestore (sufijo típico de todos los jobs de restauración del LS) por la cadena LSRestoreJobSchedule. Por ejemplo, en nuestro caso, con un job llamado LSRestore_JNSPAIN_DW_Comun_BKESync, y cuya programación es la que viene por defecto, DefaultRestoreJobSchedule, este script nos cambiaría el nombre a LSRestoreJobSchedule_JNSPAIN_DW_Comun_BKESync.

Este paso anterior en realidad no es necesario, pero en general tener el mismo nombre en muchos objetos diferentes (en realidad cada Schedule es diferente porque tienen un id diferente) no es una buena idea.

El siguiente paso consiste sencillamente en reprogramar todos estos jobs. Lo hacemos en base a una distribución aleatoria. Para ello podemos usar el siguiente script.

DECLARE @schedule_name AS VARCHAR(100);
DECLARE @schedule_id AS VARCHAR(1000);
DECLARE @period AS INT;DECLARE @minute AS INT;
DECLARE @second AS INT;
DECLARE schedules  CURSOR FOR
   SELECT distinct(name), 
          schedule_id 
   FROM msdb.dbo.sysschedules 
   WHERE name like 'LS%'

OPEN schedules
FETCH NEXT FROM schedules INTO @schedule_name, @schedule_id

WHILE @@FETCH_STATUS = 0
BEGIN    
   SET @period = (ROUND (9 * RAND(),0) + 1);    
   SET @minute =  (ROUND (9 * RAND(),0));    
   SET @second =  (ROUND (59 * RAND(),0));    

   PRINT N'-- ' + @schedule_name    
   PRINT  N'exec msdb.dbo.sp_update_schedule @schedule_id = ' + @schedule_id + ',@freq_subday_interval = ' + CAST ( @period  AS VARCHAR (2 )) + ', @active_start_time = ' + RIGHT('00'+CAST(@minute AS VARCHAR(2)),2) + RIGHT('00'+CAST(@second AS VARCHAR(2)),2)    
FETCH NEXT FROM schedules INTO @schedule_name, @schedule_id
END

CLOSE schedules;
DEALLOCATE schedules;

Esto nos devuelve un texto que se puede generar para reprogramar todos los Schedules. La salida es la siguiente :

-- LSRestoreJobSchedule_JNSPAIN_Agencias
exec msdb.dbo.sp_update_schedule @schedule_id = 10,@freq_subday_interval = 2, @active_start_time = 0640
-- LSRestoreJobSchedule_JNSPAIN_BD_BookingsRealTime
exec msdb.dbo.sp_update_schedule @schedule_id = 13,@freq_subday_interval = 4, @active_start_time = 0345
-- LSRestoreJobSchedule_BD_Mantenimiento
exec msdb.dbo.sp_update_schedule @schedule_id = 17,@freq_subday_interval = 5, @active_start_time = 0738
-- LSCopyJobSchedule_DW_Comun_BKESync
exec msdb.dbo.sp_update_schedule @schedule_id = 22,@freq_subday_interval = 4, @active_start_time = 0209
-- LSRestoreJobSchedule_DW_ComunSync
exec msdb.dbo.sp_update_schedule @schedule_id = 25,@freq_subday_interval = 2, @active_start_time = 0845
-- LSRestoreJobSchedule_BD_BookingEngine
exec msdb.dbo.sp_update_schedule @schedule_id = 27,@freq_subday_interval = 3, @active_start_time = 0044
-- LSRestoreJobSchedule_BD_Hutchison
exec msdb.dbo.sp_update_schedule @schedule_id = 29,@freq_subday_interval = 5, @active_start_time = 0141

Si lo ejecutamos ya tendremos distribuídas todas las programaciones. Se puede usar este mismo script para hacer lo mismo con los jobs de backup del LogShipping (o cualquier otro tipo de job).

Generar scripts de forma dinámica para ejecutar posteriormente es algo que hago muy a menudo. Es una herramienta muy práctica para usar o bien manualmente o bien a través del stored sp_executesql.

 

 

 

 

 

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s