כשאנחנו מגדירים Log Shipping, נוצרים ארבעה ג'ובים:
גיבוי: מבצע גיבוי לוג על השרת הראשי, מתעד זאת בטבלת היסטוריה ומוחק גיבויים ונתונים היסטוריים ישנים
העתקה: מעתיק את קבצי הגיבוי לשרת המשני ומתעד זאת בטבלה היסטוריה
שחזור: משחזר את גיבויי הלוג בשרת המשני, מתעד זאת בטבלת היסטוריה ומוחק גיבויים ונתונים היסטוריים ישנים
התרעה: מרים התרעה כאשר גיבוי או שחזור לא בוצע במשך זמן מסוים
אחד הלקוחות שלנו רצה להקים Log Shipping בשביל היכולת להתאוששות מאסון. בנוסף, הוא ציין שלא בטוח ששני השרתים יהיו מחוברים ביניהם ישירות, ושהצעד של העתקת הגיבוי בין השרתים יבוצע ע"י תהליך חיצוני בגלל חיבור רשת לא מאוד אמין.
השאלה היא: האם ניתן להקים Log Shipping ולמחוק את הג'וב של ההעתקה, או שכל החלקים בתהליך חייבים לרוץ?
התחלנו לבדוק:
1. הגדרנו Log Shipping בין שני שרתים שמחוברים ביניהם
2. עשינו Disable לג'וב ההעתקה
3. ניתקנו שרת אחד מהרשת
4. הרצנו את ג'וב הגיבוי
5. העתקנו ידנית את קובץ גיבוי הלוג שנוצר מהשרת הראשי למשני
6. הרצנו את ג'וב השחזור
והכל עבד מצוין!
כדי לוודא שלא פספסנו שום דבר, הלכנו לתיעוד של Log Shipping ושל sqllogship, שזו התוכנה שהג'ובים קוראים לה ובפועל מבצעת את העבודה. כמו שניתן לראות בתיעוד, הג'ובים שמבצעים את הגיבוי, ההעתקה והשחזור מתעדים את הפעילות שלהם, אבל לא תלויים אחד בשני. ג'וב ההתרעה (שלא היה נחוץ אצל הלקוח) לא מנטר את ג'וב ההעתקה, אלא רק האם גיבוי/שחזור לא התבצעו במשך זמן מסוים.
הצעד האחרון היה לייצר את הסקריפטים הנדרשים כדי להריץ אותם על מערכת ה-Production. מכיוון ששני השתרים לא יהיו מחוברים ביניהם, לא ניתן לעשות זאת דרך ה-Wizard. בגלל זה, יצרנו Log Shipping שוב על מערכת הבדיקות בעזרת ה-Wizard ויצרנו סקריפט של הקונפיגורציה. לאחר מכן הפרדנו את הסקריפט לשניים: אחד עבור השרת הראשי ואחד עבור המשני.
כדי לחסוך לכם את הטרחה, הנה שני הסקריפטים שנחוצים כדי לייצר Log Shipping בתצורה כזו.
אתם יכולים להוריד אותם מכאן או לצפות בקוד בהמשך.
LogShippingWithNoCopy_Secondary
/*========================================================================================================================
DO NOT RUN THIS SCRIPT WITHOUT FULLY TESTING IT AND UNDERSTANDING WHAT IT DOES
Description: This script adds a Log Shipping Secondary and deletes the copy job
Author: Matan Yungman, http://www.madeirasql.com/log-shipping-without-shipping-the-log
Created: 25/03/2015
Last Updated: 25/03/2015
Notes: Make sure to change the variable values to fit your environment
The script needs to be run at the Secondary in the context of the [msdb] database.
=========================================================================================================================*/
-------------------------------------------------------------------------------------
-- Adding the Log Shipping configuration
DECLARE
@primary_server SYSNAME = N'YourPrimaryServer',
@primary_database SYSNAME = N'YourPrimaryDatabase',
@secondary_database SYSNAME = N'YourSecondaryDatabase',
@copy_job_name SYSNAME = N'LSCopy',
@restore_job_name SYSNAME = N'LSRestore',
@backup_source_directory NVARCHAR(500) = N'\\YourShare\DBBackup' ,
@backup_destination_directory NVARCHAR(500) = N'C:\BackupFilesFromPrimary'
DECLARE @LS_Secondary__CopyJobId AS uniqueidentifier
DECLARE @LS_Secondary__RestoreJobId AS uniqueidentifier
DECLARE @LS_Secondary__SecondaryId AS uniqueidentifier
DECLARE @LS_Add_RetCode As int
--Delete log shipping (if it exists)
EXEC sp_delete_log_shipping_secondary_database
@secondary_database = @secondary_database
IF EXISTS(SELECT * FROM msdb.dbo.sysjobs WHERE name = @restore_job_name)
BEGIN
EXEC msdb.dbo.sp_delete_job @job_name = @restore_job_name
END
IF EXISTS(SELECT * FROM msdb.dbo.sysjobs WHERE name = @copy_job_name)
BEGIN
EXEC msdb.dbo.sp_delete_job @job_name = @copy_job_name
END
--Add Log Shipping
EXEC @LS_Add_RetCode = master.dbo.sp_add_log_shipping_secondary_primary
@primary_server = @primary_server
,@primary_database = @primary_database
,@backup_source_directory = @backup_source_directory
,@backup_destination_directory = @backup_destination_directory
,@copy_job_name = @copy_job_name
,@restore_job_name = @restore_job_name
,@file_retention_period = 4320
,@overwrite = 1
,@copy_job_id = @LS_Secondary__CopyJobId OUTPUT
,@restore_job_id = @LS_Secondary__RestoreJobId OUTPUT
,@secondary_id = @LS_Secondary__SecondaryId OUTPUT
IF (@@ERROR = 0 AND @LS_Add_RetCode = 0)
BEGIN
DECLARE @LS_SecondaryCopyJobScheduleUID As uniqueidentifier
DECLARE @LS_SecondaryCopyJobScheduleID AS int
EXEC msdb.dbo.sp_add_schedule
@schedule_name =N'DefaultCopyJobSchedule'
,@enabled = 1
,@freq_type = 4
,@freq_interval = 1
,@freq_subday_type = 4
,@freq_subday_interval = 5
,@freq_recurrence_factor = 0
,@active_start_date = 20150322
,@active_end_date = 99991231
,@active_start_time = 0
,@active_end_time = 235900
,@schedule_uid = @LS_SecondaryCopyJobScheduleUID OUTPUT
,@schedule_id = @LS_SecondaryCopyJobScheduleID OUTPUT
EXEC msdb.dbo.sp_attach_schedule
@job_id = @LS_Secondary__CopyJobId
,@schedule_id = @LS_SecondaryCopyJobScheduleID
DECLARE @LS_SecondaryRestoreJobScheduleUID As uniqueidentifier
DECLARE @LS_SecondaryRestoreJobScheduleID AS int
EXEC msdb.dbo.sp_add_schedule
@schedule_name =N'DefaultRestoreJobSchedule'
,@enabled = 1
,@freq_type = 4
,@freq_interval = 1
,@freq_subday_type = 4
,@freq_subday_interval = 5
,@freq_recurrence_factor = 0
,@active_start_date = 20150322
,@active_end_date = 99991231
,@active_start_time = 0
,@active_end_time = 235900
,@schedule_uid = @LS_SecondaryRestoreJobScheduleUID OUTPUT
,@schedule_id = @LS_SecondaryRestoreJobScheduleID OUTPUT
EXEC msdb.dbo.sp_attach_schedule
@job_id = @LS_Secondary__RestoreJobId
,@schedule_id = @LS_SecondaryRestoreJobScheduleID
END
DECLARE @LS_Add_RetCode2 As int
IF (@@ERROR = 0 AND @LS_Add_RetCode = 0)
BEGIN
EXEC @LS_Add_RetCode2 = master.dbo.sp_add_log_shipping_secondary_database
@secondary_database = @secondary_database
,@primary_server = @primary_server
,@primary_database = @primary_database
,@restore_delay = 0
,@restore_mode = 1
,@disconnect_users = 1
,@restore_threshold = 45
,@threshold_alert_enabled = 0
,@history_retention_period = 5760
,@overwrite = 1
END
IF (@@error = 0 AND @LS_Add_RetCode = 0)
BEGIN
EXEC msdb.dbo.sp_update_job
@job_id = @LS_Secondary__CopyJobId
,@enabled = 1
EXEC msdb.dbo.sp_update_job
@job_id = @LS_Secondary__RestoreJobId
,@enabled = 1
END
--Delete the copy job
EXEC msdb.dbo.sp_delete_job @job_name = @copy_job_name
LogShippingWithNoCopy_Primary
/*========================================================================================================================
DO NOT RUN THIS SCRIPT WITHOUT FULLY TESTING IT AND UNDERSTANDING WHAT IT DOES
Description: This script adds a Log Shipping Primary
Author: Matan Yungman, http://www.madeirasql.com/log-shipping-without-shipping-the-log
Created: 25/03/2015
Last Updated: 25/03/2015
Notes: Make sure to change the variable values to fit your environment
The script needs to be run at the Primary in the context of the [msdb] database.
=========================================================================================================================*/
-------------------------------------------------------------------------------------
-- Adding the Log Shipping configuration
-- ****** Begin: Script to be run at Primary ******
DECLARE
@primary_database SYSNAME = N'YourPrimaryServer',
@secondary_server SYSNAME = N'YourSecondaryServer',
@secondary_database SYSNAME = N'YourSecondaryDatabase',
@backup_job_name SYSNAME = N'LSBackup',
@backup_directory NVARCHAR(500) = N'C:\Backup',
@backup_share NVARCHAR(500) = N'\\YourShare\DBBackup'
DECLARE @LS_BackupJobId AS uniqueidentifier
DECLARE @LS_PrimaryId AS uniqueidentifier
DECLARE @SP_Add_RetCode As int
--Drop log shipping (if it exists)
EXEC sp_delete_log_shipping_primary_secondary
@primary_database = @primary_database,
@secondary_server = @secondary_server,
@secondary_database = @secondary_database
EXEC sp_delete_log_shipping_primary_database
@database = @primary_database
IF EXISTS(SELECT * FROM msdb.dbo.sysjobs WHERE name = @backup_job_name)
BEGIN
EXEC msdb.dbo.sp_delete_job @job_name = @backup_job_name
END
EXEC @SP_Add_RetCode = master.dbo.sp_add_log_shipping_primary_database
@database = @primary_database
,@backup_directory = @backup_directory
,@backup_share = @backup_share
,@backup_job_name = @backup_job_name
,@backup_retention_period = 4320
,@backup_threshold = 60
,@threshold_alert_enabled = 0
,@history_retention_period = 5760
,@backup_job_id = @LS_BackupJobId OUTPUT
,@primary_id = @LS_PrimaryId OUTPUT
,@overwrite = 1
IF (@@ERROR = 0 AND @SP_Add_RetCode = 0)
BEGIN
DECLARE @LS_BackUpScheduleUID As uniqueidentifier
DECLARE @LS_BackUpScheduleID AS int
EXEC msdb.dbo.sp_add_schedule
@schedule_name =N'LSBackupSchedule'
,@enabled = 1
,@freq_type = 4
,@freq_interval = 1
,@freq_subday_type = 4
,@freq_subday_interval = 5
,@freq_recurrence_factor = 0
,@active_start_date = 20150322
,@active_end_date = 99991231
,@active_start_time = 0
,@active_end_time = 235900
,@schedule_uid = @LS_BackUpScheduleUID OUTPUT
,@schedule_id = @LS_BackUpScheduleID OUTPUT
EXEC msdb.dbo.sp_attach_schedule
@job_id = @LS_BackupJobId
,@schedule_id = @LS_BackUpScheduleID
EXEC msdb.dbo.sp_update_job
@job_id = @LS_BackupJobId
,@enabled = 1
END
EXEC master.dbo.sp_add_log_shipping_alert_job
EXEC master.dbo.sp_add_log_shipping_primary_secondary
@primary_database = @primary_database
,@secondary_server = @secondary_server
,@secondary_database = @secondary_database
,@overwrite = 1