משיב מוביל
תהליך שחזור DB יומי נכשל.

שאלה
-
יש לי תהליך יומי שמשחזר DB משרת אחד לשרת אחר.
הוא משחזר את קובץ הגיבוי של ה-DB, ואם הוא מוצא קבצי Tlog backup הוא משחזר גם אותם.התהליך עובד כהלכה מזה זמן רב.
היום בבוקר הוא נכשל.הודעת השגיאה:
Message Executed as user: AOI\sa_SqlAgentSrv_PRD. RegQueryValueEx() returned error 2, 'The system cannot find the file specified.' [SQLSTATE 01000] (Message 22001) IF EXISTS (select * from sysdatabases where name = 'SiteDbStandby') ALTER DATABASE SiteDbStandby SET SINGLE_USER WITH ROLLBACK IMMEDIATE RESTORE DATABASE [SiteDbStandby] FROM DISK = '\\SqlBackup\Databases\SiteDb.bak' WITH NORECOVERY , REPLACE , MOVE 'SiteDb_data' to 'G:\MSSQL10.DB2\MSSQL\DATA\SiteDbStandby_SiteDb_data.mdf' , MOVE 'SiteDb_log' to 'J:\MSSQL10.DB2\MSSQL\DATA\SiteDbStandby_SiteDb_log.ndf' [SQLSTATE 01000] (Message 0) Processed 191216 pages for database 'SiteDbStandby', file 'SiteDb_data' on file 1. [SQLSTATE 01000] (Message 4035) Processed 4 pages for database 'SiteDbStandby', file 'SiteDb_log' on file 1. [SQLSTATE 01000] (Message 4035) RESTORE DATABASE successfully processed 191220 pages in 20.366 seconds (73.352 MB/sec). [SQLSTATE 01000] (Message 3014) RESTORE LOG SiteDbStandby FROM DISK = '\\SqlBackup\Logs\SiteDb_20120916_011017.BAK' WITH NORECOVERY RESTORE LOG SiteDbStandby FROM DISK = '\\SqlBackup\Logs\SiteDb_20120916_021929.BAK' WITH NORECOVERY RESTORE LOG SiteDbStandby FROM DISK = '\\SqlBackup\Logs\SiteDb_20120916_031349.BAK' WITH NORECOVERY RESTORE LOG SiteDbStandby FROM DISK = '\\SqlBackup\Logs\SiteDb_20120915_231017.BAK' WITH NORECOVERY RESTORE LOG SiteDbStandby FROM DISK = '\\SqlBackup\Logs\SiteDb_20120916_001017.BAK' WITH NORECOVERY
[SQLSTATE 01000] (Message 0) The log in this backup set begins at LSN 42459000001303500001, which is too recent to apply to the database. An earlier log backup that includes LSN 42459000001302800001 can be restored. [SQLSTATE 42000] (Error 4305) RESTORE LOG is terminating abnormally. [SQLSTATE 42000] (Error 3013). The step failed.חדי העין ישימו לב שהוא מנסה לשחזר את קובץ הלוג של 16.9 ב-1 בלילה, את קובץ הלוג של 16.9 ב-2 בלילה, את קובץ הלוג של 16.9 ב-3 בלילה,
ואז את קובץ הלוג של 15.9 ב-23 בלילה, ואת קובץ הלוג של 16.9 ב-12 בלילה.כלומר, משהו התחרבש בסדר שיחזור הלוגים.
הסתכלתי אחורה בהיסטוריה של הג'וב, נשמרות הרצות של כשלושה שבועות אחורה, בכל אחת מההרצות הסדר הוא נכון, לדוגמא:
Executed as user: AOI\sa_SqlAgentSrv_PRD. RegQueryValueEx() returned error 2, 'The system cannot find the file specified.' [SQLSTATE 01000] (Message 22001) IF EXISTS (select * from sysdatabases where name = 'SiteDbStandby') ALTER DATABASE SiteDbStandby SET SINGLE_USER WITH ROLLBACK IMMEDIATE RESTORE DATABASE [SiteDbStandby] FROM DISK = '\\SqlBackup\Databases\SiteDb.bak' WITH NORECOVERY , REPLACE , MOVE 'SiteDb_data' to 'G:\MSSQL10.DB2\MSSQL\DATA\SiteDbStandby_SiteDb_data.mdf' , MOVE 'SiteDb_log' to 'J:\MSSQL10.DB2\MSSQL\DATA\SiteDbStandby_SiteDb_log.ndf' [SQLSTATE 01000] (Message 0) Processed 191032 pages for database 'SiteDbStandby', file 'SiteDb_data' on file 1. [SQLSTATE 01000] (Message 4035) Processed 6 pages for database 'SiteDbStandby', file 'SiteDb_log' on file 1. [SQLSTATE 01000] (Message 4035) RESTORE DATABASE successfully processed 191038 pages in 21.703 seconds (68.768 MB/sec). [SQLSTATE 01000] (Message 3014) RESTORE LOG SiteDbStandby FROM DISK = '\\SqlBackup\Logs\SiteDb_20120914_231026.BAK' WITH NORECOVERY RESTORE LOG SiteDbStandby FROM DISK = '\\SqlBackup\Logs\SiteDb_20120915_001019.BAK' WITH NORECOVERY RESTORE LOG SiteDbStandby FROM DISK = '\\SqlBackup\Logs\SiteDb_20120915_011032.BAK' WITH NORECOVERY RESTORE LOG SiteDbStandby FROM DISK = '\\SqlBackup\Logs\SiteDb_20120915_021140.BAK' WITH NORECOVERY RESTORE LOG SiteDbStandby FROM DISK = '\\SqlBackup\Logs\SiteDb_20120915_031053.BAK' WITH NORECOVERY [SQLSTATE 01000] (Message 0) Processed 0 pages for database 'SiteDbStandby', file 'SiteDb_data' on file 1. [SQLSTATE 01000] (Message 4035) Processed 7 pages for database 'SiteDbStandby', file 'SiteDb_log' on file 1. [SQLSTATE 01000] (Message 4035) RESTORE LOG successfully processed 7 pages in 0.009 seconds (5.588 MB/sec). [SQLSTATE 01000] (Message 3014) Processed 0 pages for database 'SiteDbStandby', file 'SiteDb_data' on file 1. [SQLSTATE 01000] (Message 4035) Processed 0 pages for database 'SiteDbStandby', file 'SiteDb_log' on file 1. [SQLSTATE 01000] (Message 4035) RESTORE LOG successfully processed 0 pages in 0.009 seconds (0.000 MB/sec). [SQLSTATE 01000] (Message 3014) Processed 0 pages for database 'SiteDbStandby', file 'SiteDb_data' on file 1. [SQLSTATE 01000] (Message 4035) Processed 1229 pages for database 'SiteDbStandby', file 'SiteDb_log' on file 1. [SQLSTATE 01000] (Message 4035) RESTORE LOG successfully processed 1229 pages in 0.196 seconds (48.965 MB/sec). [SQLSTATE 01000] (Message 3014) Processed 0 pages for database 'SiteDbStandby', file 'SiteDb_data' on file 1. [SQLSTATE 01000] (Message 4035) Processed 3 pages for database 'SiteDbStandby', file 'SiteDb_log' on file 1. [SQLSTATE 01000] (Message 4035) RESTORE LOG successfully processed 3 pages in 0.013 seconds (1.277 MB/sec). [SQLSTATE 01000] (Message 3014) Processed 0 pages for database 'SiteDbStandby', file 'SiteDb_data' on file 1. [SQLSTATE 01000] (Message 4035) Processed 0 pages for database 'SiteDbStandby', file 'SiteDb_log' on file 1. [SQLSTATE 01000] (Message 4035) RESTORE LOG successfully processed 0 pages in 0.009 seconds (0.000 MB/sec). [SQLSTATE 01000] (Message 3014) use master restore database SiteDbStandby with recovery [SQLSTATE 01000] (Message 0) RESTORE DATABASE successfully processed 0 pages in 4.360 seconds (0.000 MB/sec). [SQLSTATE 01000] (Message 3014) use SiteDbStandby ALTER AUTHORIZATION ON DATABASE::SiteDbStandby TO sa ALTER DATABASE SiteDbStandby SET COMPATIBILITY_LEVEL = 100 [SQLSTATE 01000] (Message 0). The step succeeded.
כלומר, קודם 23 בלילה של היום הקודם, 12 בלילה של היום חדש, ואז 1,2,3 בלילה של היום החדש.
כל הלוגים קיימים במקומם בתיקיית הגיבויים, הכל עושה רושם תקין.
יש למישהו רעיון למה הג'וב נכשל?
חג שמח, אגב :)
תודה מראש,
רוני
תשובות
-
היי רוני !
טוב אז כמו שחשדתי כאשר בונים בסקריפט את פקודת השחזור עבור קבצי הלוג (בדרך כלל הסיומת שלהם היא trn אבל אצלכם היא גם כן bak כמו קבצי הFULL אבל זה לא קריטי..)
אז בסקריפט נשלפים כל הקבצים שהתאריך שלהם באמת התבצע אחרי גיבוי הFULL האחרון וזה פאנן.
הבעייתיות היחידה היא שכאשר בונים את פקודות השחזור לא מחייב שבונים אותם על פי הסדר הכרונולוגי המתאים בגלל שאין את פקודת הORDER BY שממיינת על פי התאריכים שבה
התבצעו הגיבויים.
ברוב המקרים לדעתי זה באמת נכון שזה יתפוס כמו הרבה שליפות שחוזרות ממויינות על פי מה שאנחנו צריכים בהרבה מאוד מקרים אבל אין זה מחייב ואת זה צריך לזכור.
לכן לדעתי זאת הייתה הבעיה שלפיה הקבצים לא חזרו ממויינים על פי התאריכים ולכן לא היה ניתן לשחזר את הלוגים ולסגור את השחזור בהצלחה.
לכן על כל פנים צריך לדאוג למיין לפי התאריכים ע"י ORDER BY ואני הייתי עושה את זה ככה במידה והתאריך עצמו הינו תמיד 8 ספרות והשעה 6 ספרות אז:-- Restore the LOG files if @sErrorMessage = '' and @bRestoreLog = 1 begin set @sBackupPath = @sBackupPath + '\Logs\' create table #tLogFiles (sFileName varchar(100), iDepth tinyint, iFile tinyint) insert into #tLogFiles exec xp_dirtree @sBackupPath,0,1 -- Retrieve all the LOG file backups from Logs directory alter table #tLogFiles -- ADD add [date] AS (substring(sFileName, charindex(N'_', sFileName) + 1, 8)) alter table #tLogFiles -- ADD add [time] AS (substring(sFileName, charindex(N'_', sFileName, charindex(N'_', sFileName) + 1) + 1, 6)) set @sSql = '' select @sSql = @sSql + 'RESTORE LOG ' + @sDatabaseNameNew + ' FROM DISK = ''' + @sBackupPath + sFileName + ''' WITH NORECOVERY' + char(13) from #tLogFiles where sFileName like @sDatabaseName + '_2%' and sFileName > @sDatabaseName + @sBackupFinishDate + '.bak' ORDER BY l.[date], l.[time] -- ADD drop table #tLogFiles print @sSql if @bScriptOnly = 0 -- Only execute the statement if the 'scriptonly' bit is not set exec (@sSql) end
גמר חתימה טובה!
חיים פישנר.
- הוצע כתשובה על-ידי Guy GlantserMVP, Moderator יום חמישי 27 ספטמבר 2012 07:40
- סומן כתשובה על-ידי Roni Vered Adar יום חמישי 27 ספטמבר 2012 11:28
כל התגובות
-
-
היי רוני, חג שמח :)!
ניראה לי שאת כבר דיי עלית על הבעיה כשאמרת ש: "כלומר, משהו התחרבש בסדר שיחזור הלוגים."
כי הגיוני שהוא לא יצליח לגלגל קובץ גיבוי של הלוג שישן מהזמן הדיבי כבר נמצא בו....
במקרה הראשון היה גלגול של לוגים כמו שרשמת והצגת עד-16/09 בשעה 3
20120916_031349
ואז "התפלק" לו לשם גיבוי לוג של יום קודם בעצם ה- 15/09 בשעה 23
20120915_231017
ואם נשים לב ללוג שאפילו אחרי זה היה אמור להתגלגל הוא גם לא תואם בזמן כי הוא חוזר גם כן אחורה אפילו שהוא בתאריך ה-16/09 כי הוא התבצע בשעה 00 ככל הנראה.
20120916_001017
בקיצור כל השאלה היא כיצד הג'וב אצלכם בונה את הפקודות RESTORE שהוא צריך לבצע ?האם הוא עושה את זה בצורה דינמית?
ומהיכן הוא מחלץ את שמות הקבצים אותם הוא צריך לשחזר ?
חיים פישנר.
- נערך על-ידי haim fishner יום שני 17 ספטמבר 2012 13:56
-
שלום רוני,
מבלי לגרוע בכל האמור לעיל, לדעתי ההודעה הנ"ל אומרת הכל:
[SQLSTATE 01000] (Message 0) The log in this backup set begins at LSN 42459000001303500001, which is too recent to apply to the database. An earlier log backup that includes LSN 42459000001302800001 can be restored. [SQLSTATE 42000] (Error 4305) RESTORE LOG is terminating abnormally. [SQLSTATE 42000] (Error 3013). The step failed.
זאת אומרת שהבעיה היא שהקובץ הוא חדש מדי ולכן לא משתחזר.
אני מבין מדברייך שהjob דינמי, האם תוכלי לפרסם כאן את הscript שבונה את ה restore ?בברכה,
נועם -
הי רוני,
רוני נשמח אם תעדכני אותנו בסטטוס השאלה.
אם אחת מן התשובות עזרה לך, אנא סמני אותה.
תודה,
צוות הפורומים.
מיקרוסופט מציעה שירות זה ללא תשלום, למטרת סיוע למשתמשים והעשרת הידע הקשור בטכנולוגיות ובמוצרים של מיקרוסופט. תוכן זה מתפרסם כפי שהוא והוא אינו מעיד על כל אחריות מצד מיקרוסופט.
-
סליחה על התגובה המאוחרת, יצאתי קצת לחופש :)
ובכן,
להלן הג'וב שאנחנו משתמשים בו (קיים כבר זמן רב, הוקם לפני שהתחלתי לעבוד כאן)
החלק הרלוונטי בסקריפט שקשור לשחזור לוגים הוא החלק שמתחיל בפקודה:
if @sErrorMessage = '' and @bRestoreLog = 1
הפקודה שאנחנו מריצים על מנת לשחזר היא:
exec dbo.pRestoreDatabase @sDatabaseName = 'SiteDb',
@sDatabaseNameNew = 'SiteDbStandby',
@bRestoreLog = 1,
@bRecover = 1, @bShrinkDatabase = 0, @bReplace = 1
create procedure [dbo].[pRestoreDatabase] (@sDatabaseName varchar(100) = '' ,@sDatabaseNameNew varchar(100) = '' ,@sBackupPath varchar(200) = '\\SqlBackup' ,@bReplace bit = 0 ,@bRestoreLog bit = 0 ,@bRecover bit = 0 ,@bShrinkDatabase bit = 0 ,@bScriptOnly bit = 0 ,@sMirrorPrincipal varchar(100) = '' ) as begin if @sDatabaseNameNew = '' set @sDatabaseNameNew = @sDatabaseName if @sMirrorPrincipal <> '' begin set @bReplace = 1 set @bRestoreLog = 1 end begin try -- Try to create the 'tBackupFileList' table. If not successfull it probably already exists and a statement will be printed to the screen. if not exists (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[tBackupFilelist]') AND type in (N'U')) begin create table dbo.tBackupFilelist (LogicalName nvarchar(128) NULL ,PhysicalName nvarchar(260) NULL ,[Type] char(1) NULL ,FileGroupName nvarchar(128) NULL ,Size numeric(20, 0) NULL ,MaxSize numeric(20, 0) NULL ,FileId int NULL ,CreateLSN numeric(25, 0) NULL ,DropLSN numeric(25, 0) NULL ,UniqueFileId uniqueidentifier NULL ,readonlyLSN numeric(25, 0) NULL ,readwriteLSN numeric(25, 0) NULL ,BackupSizeInBytes bigint NULL ,SourceBlkSize int NULL ,FileGroupId int NULL ,LogGroupGuid uniqueidentifier NULL ,DifferentialBaseLsn numeric(25, 0) NULL ,DifferentialBaseGuid uniqueidentifier NULL ,IsReadOnly bit NULL ,IsPresent bit NULL ,TDEThumbprint varbinary(32) NULL ) on [PRIMARY] end end try begin catch print 'Error! -> Table ''tBackupFilelist'' could not be created and doesn''t exist.' end catch begin try -- Try to create the 'tBackupHeader' table. If not successfull it probably already exists and a statement will be printed to the screen. if not exists (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[tBackupHeader]') AND type in (N'U')) begin create table dbo.tBackupHeader (BackupName sysname NULL ,BackupDescription sysname NULL ,BackupType int NULL ,ExpirationDate datetime NULL ,Compressed bit NULL ,Position int NULL ,DeviceType int NULL ,UserName sysname NULL ,ServerName sysname NULL ,DatabaseName sysname NULL ,DatabaseVersion int NULL ,DatabaseCreationDate datetime NULL ,BackupSize numeric(38, 0) NULL ,FirstLsn numeric(38, 0) NULL ,LastLsn numeric(38, 0) NULL ,CheckpointLsn numeric(38, 0) NULL ,DifferentialBaseLsn numeric(38, 0) NULL ,BackupStartDate datetime NULL ,BackupFinishDate datetime NULL ,SortOrder int NULL ,[CodePage] int NULL ,UnicodeLocaleId int NULL ,UnicodeComparisonStyle int NULL ,CompatibilityLevel int NULL ,SoftwareVendorId int NULL ,SoftwareVersionMajor int NULL ,SoftwareVersionMinor int NULL ,SoftwareVersionBuild int NULL ,MachineName sysname NULL ,Flags int NULL ,BindingId uniqueidentifier NULL ,RecoveryForkId uniqueidentifier NULL ,Collation sysname NULL ,FamilyGUID uniqueidentifier NULL ,HasBulkLoggedData bit NULL ,IsSnapshot bit NULL ,IsReadOnly bit NULL ,IsSingleUser bit NULL ,HasBackupChecksums bit NULL ,IsDamaged bit NULL ,BeginsLogChain bit NULL ,HasIncompleteMetaData bit NULL ,IsForceOffline bit NULL ,IsCopyOnly bit NULL ,FirstRecoveryForkID uniqueidentifier NULL ,ForkPointLSN numeric(38, 0) NULL ,RecoveryModel sysname NULL ,DatabaseBackupLSN numeric(38, 0) NULL ,DifferentialBaseGUID uniqueidentifier NULL ,BackupTypeDescription sysname NULL ,BackupSetGUID uniqueidentifier NULL ,CompressedBackupSize numeric(38, 0) NULL ) on [PRIMARY] end end try begin catch print 'Error! -> Table ''tBackupHeader'' could not be created and doesn''t exist.' end catch declare @sSql varchar(8000) ,@sDataPath nvarchar(512) ,@sLogPath nvarchar(512) ,@sBackupFinishDate varchar(100) ,@dStart datetime ,@sErrorMessage varchar(1000) select @sErrorMessage = '' ,@dStart = GETDATE() exec master.dbo.xp_instance_regread N'HKEY_LOCAL_MACHINE', N'Software\Microsoft\MSSQLServer\MSSQLServer', N'DefaultData', @sDataPath OUTPUT if @sDataPath is null begin begin try exec master.dbo.xp_instance_regread N'HKEY_LOCAL_MACHINE', N'Software\Microsoft\MSSQLServer\MSSQLServer\Parameters', N'SQLArg0', @sDataPath OUTPUT set @sDataPath = substring(@sDataPath, 3, 255) set @sDataPath = substring(@sDataPath, 1, len(@sDataPath) - charindex('\', reverse(@sDataPath))) end try begin catch print 'Warning: The Default data path could not be read from the registry.' end catch end begin try exec master.dbo.xp_instance_regread N'HKEY_LOCAL_MACHINE', N'Software\Microsoft\MSSQLServer\MSSQLServer', N'DefaultLog', @sLogPath OUTPUT end try begin catch print 'Warning: The default log path could not be read from the registry.' end catch if @sLogPath is null set @sLogPath = @sDataPath truncate table tBackupFileList set @sSql = 'RESTORE FILELISTONLY FROM DISK = ''' + @sBackupPath + '\Databases\' + @sDatabaseName + '.bak''' insert into tBackupFileList exec(@sSql) truncate table tBackupHeader set @sSql = 'RESTORE HEADERONLY FROM DISK = ''' + @sBackupPath + '\Databases\' + @sDatabaseName + '.bak''' insert into tBackupHeader exec(@sSql) -- Save the Backup Finish date into variable (this variable is later being used in the restoration select @sBackupFinishDate = '_' + replace(replace(replace(convert(varchar(16), BackupFinishDate, 20), '-', ''), ':', ''), ' ', '_') from tBackupHeader ---------------------------------------------------------------------------------------------------------------------------------------------- -- 1. Start building the restore statement set @sSql = 'IF EXISTS (select * from sysdatabases where name = ''' + @sDatabaseNameNew + ''')' + CHAR(13) + ' ALTER DATABASE ' + @sDatabaseNameNew + ' SET SINGLE_USER WITH ROLLBACK IMMEDIATE ' + CHAR(13) + 'RESTORE DATABASE [' + @sDatabaseNameNew + ']' + char(13) + 'FROM DISK = ''' + @sBackupPath + '\Databases\' + @sDatabaseName + '.bak''' + CHAR(13) + 'WITH NORECOVERY ' + CHAR(13) ------------------------------------------ -- 2. Add the Replace option if denoted if @bReplace = 1 set @sSql = @sSql + ', REPLACE' + CHAR(13) ------------------------------------------ -- 3. Add the 'MOVE' option if denoted select @sSql = @sSql + ', MOVE ''' + LogicalName + ''' to ''' + case type when 'L' then @sLogPath else @sDataPath end + '\' + case when @sDatabaseNameNew <> @sDatabaseName then @sDatabaseNameNew + '_' else '' end + right(PhysicalName, charindex('\', reverse(PhysicalName))- 1) + '''' + CHAR(13) from tBackupFileList order by Type ,FileId ------------------------------------------ -- 4. Execute the restore statement. begin try print @sSql if @bScriptOnly = 0 -- Only execute the statement if the 'scriptonly' bit is not set exec (@sSql) -- Execute the restore statement end try begin catch set @sErrorMessage = ERROR_MESSAGE() end catch ---------------------------------------------------------------------------------------------------------------------------------------------- -- Restore the LOG files if @sErrorMessage = '' and @bRestoreLog = 1 begin set @sBackupPath = @sBackupPath + '\Logs\' create table #tLogFiles (sFileName varchar(100), iDepth tinyint, iFile tinyint) insert into #tLogFiles exec xp_dirtree @sBackupPath,0,1 -- Retrieve all the LOG file backups from Logs directory set @sSql = '' select @sSql = @sSql + 'RESTORE LOG ' + @sDatabaseNameNew + ' FROM DISK = ''' + @sBackupPath + sFileName + ''' WITH NORECOVERY' + char(13) from #tLogFiles where sFileName like @sDatabaseName + '_2%' and sFileName > @sDatabaseName + @sBackupFinishDate + '.bak' drop table #tLogFiles print @sSql if @bScriptOnly = 0 -- Only execute the statement if the 'scriptonly' bit is not set exec (@sSql) end ---------------------------------------------------------------------------------------------------------------------------------------------- -- Set the Partner database (used for Database mirroring setup) if @sErrorMessage = '' and @sMirrorPrincipal <> '' begin set @sSql = 'ALTER DATABASE ' + @sDatabaseNameNew + ' SET PARTNER = ''' + @sMirrorPrincipal + '''' print @sSql if @bScriptOnly = 0 -- Only execute the statement if the 'scriptonly' bit is not set exec (@sSql) end ---------------------------------------------------------------------------------------------------------------------------------------------- -- Recover the database (...and other stuff that can only be done on recovered databases) if @sErrorMessage = '' and @bRecover = 1 begin waitfor delay '000:00:03' set @sSql = 'use master' + CHAR(13) + 'restore database ' + @sDatabaseNameNew + ' with recovery' + CHAR(13) print @sSql if @bScriptOnly = 0 -- Only execute the statement if the 'scriptonly' bit is not set exec (@sSql) while @@rowcount > 0 begin waitfor delay '000:00:03' select * from sys.databases where name = @sDatabaseNameNew and state_desc <> 'ONLINE' end -------------------------------------------------------------------------------------------- -- Set authorization and compatibility level set @sSql = 'use ' + @sDatabaseNameNew + CHAR(13) + 'ALTER AUTHORIZATION ON DATABASE::' + @sDatabaseNameNew + ' TO sa' + CHAR(13) + 'ALTER DATABASE ' + @sDatabaseNameNew + ' SET COMPATIBILITY_LEVEL = 100' + CHAR(13) -------------------------------------------------------------------------------------------- -- Shrink the database if @bShrinkDatabase = 1 begin set @sSql = @sSql + 'ALTER DATABASE ' + @sDatabaseNameNew + ' SET RECOVERY SIMPLE' + CHAR(13) select @sSql = @sSql + 'DBCC SHRINKFILE (N''' + LogicalName + ''' , 1)' + CHAR(13) from tBackupFilelist order by Type end begin try print @sSql if @bScriptOnly = 0 -- Only execute the statement if the 'scriptonly' bit is not set exec (@sSql) end try begin catch set @sErrorMessage = ERROR_MESSAGE() end catch end ---------------------------------------------------------------------------------------------------------------------------------------------- -- Log everything within the Datamanagement database for future reference if @bScriptOnly = 0 -- Only execute the statement if the 'scriptonly' bit is not set begin set @sSql = '''' + @@servername + ''',''' + @sDatabaseNameNew + ''',''DR'',''' + @sBackupPath + '\Databases'',''' + @sDatabaseName + '.bak'',''' + convert(char(19), @dStart, 120) + ''',''' + convert(char(19), getdate(), 120) + ''',''' + system_user + ''',''' + @sErrorMessage + '''' exec master.dbo.pCreateLogFile @sFileName = 'tHistoryBackupRestore' ,@sQuery = @sSql end end
-
היי רוני !
טוב אז כמו שחשדתי כאשר בונים בסקריפט את פקודת השחזור עבור קבצי הלוג (בדרך כלל הסיומת שלהם היא trn אבל אצלכם היא גם כן bak כמו קבצי הFULL אבל זה לא קריטי..)
אז בסקריפט נשלפים כל הקבצים שהתאריך שלהם באמת התבצע אחרי גיבוי הFULL האחרון וזה פאנן.
הבעייתיות היחידה היא שכאשר בונים את פקודות השחזור לא מחייב שבונים אותם על פי הסדר הכרונולוגי המתאים בגלל שאין את פקודת הORDER BY שממיינת על פי התאריכים שבה
התבצעו הגיבויים.
ברוב המקרים לדעתי זה באמת נכון שזה יתפוס כמו הרבה שליפות שחוזרות ממויינות על פי מה שאנחנו צריכים בהרבה מאוד מקרים אבל אין זה מחייב ואת זה צריך לזכור.
לכן לדעתי זאת הייתה הבעיה שלפיה הקבצים לא חזרו ממויינים על פי התאריכים ולכן לא היה ניתן לשחזר את הלוגים ולסגור את השחזור בהצלחה.
לכן על כל פנים צריך לדאוג למיין לפי התאריכים ע"י ORDER BY ואני הייתי עושה את זה ככה במידה והתאריך עצמו הינו תמיד 8 ספרות והשעה 6 ספרות אז:-- Restore the LOG files if @sErrorMessage = '' and @bRestoreLog = 1 begin set @sBackupPath = @sBackupPath + '\Logs\' create table #tLogFiles (sFileName varchar(100), iDepth tinyint, iFile tinyint) insert into #tLogFiles exec xp_dirtree @sBackupPath,0,1 -- Retrieve all the LOG file backups from Logs directory alter table #tLogFiles -- ADD add [date] AS (substring(sFileName, charindex(N'_', sFileName) + 1, 8)) alter table #tLogFiles -- ADD add [time] AS (substring(sFileName, charindex(N'_', sFileName, charindex(N'_', sFileName) + 1) + 1, 6)) set @sSql = '' select @sSql = @sSql + 'RESTORE LOG ' + @sDatabaseNameNew + ' FROM DISK = ''' + @sBackupPath + sFileName + ''' WITH NORECOVERY' + char(13) from #tLogFiles where sFileName like @sDatabaseName + '_2%' and sFileName > @sDatabaseName + @sBackupFinishDate + '.bak' ORDER BY l.[date], l.[time] -- ADD drop table #tLogFiles print @sSql if @bScriptOnly = 0 -- Only execute the statement if the 'scriptonly' bit is not set exec (@sSql) end
גמר חתימה טובה!
חיים פישנר.
- הוצע כתשובה על-ידי Guy GlantserMVP, Moderator יום חמישי 27 ספטמבר 2012 07:40
- סומן כתשובה על-ידי Roni Vered Adar יום חמישי 27 ספטמבר 2012 11:28
-
רק להסבר אני הוספתי 2 עמודות מחושבות על השם של הקובץ שמפרסר את השם של הקובץ בעצם ומוציא את התאריך והשעה ואז ממיין קודם לפי התאריך ואז לפי השעה.
יש מצב גדול אפילו שניתן לחסוך את כל זה על ידי כך שנמיין לפי שם הקובץ אבל צריך לחשוב טיפה האם ישנה אופציה שזה יפול בגלל שזה מיון של מחרוזת (מילוני) ואם ישנה אופציה
שהמיון המילוני לא יהיה נכון למרות שלא ניראה לי שזה יכול לקרות במקרה הזה אבל שוב צריך לחשוב מעט.
במקרה השני זה יראה ככה:
-- Restore the LOG files if @sErrorMessage = '' and @bRestoreLog = 1 begin set @sBackupPath = @sBackupPath + '\Logs\' create table #tLogFiles (sFileName varchar(100), iDepth tinyint, iFile tinyint) insert into #tLogFiles exec xp_dirtree @sBackupPath,0,1 -- Retrieve all the LOG file backups from Logs directory set @sSql = '' select @sSql = @sSql + 'RESTORE LOG ' + @sDatabaseNameNew + ' FROM DISK = ''' + @sBackupPath + sFileName + ''' WITH NORECOVERY' + char(13) from #tLogFiles where sFileName like @sDatabaseName + '_2%' and sFileName > @sDatabaseName + @sBackupFinishDate + '.bak' ORDER BY l.sFileName -- ADD drop table #tLogFiles print @sSql if @bScriptOnly = 0 -- Only execute the statement if the 'scriptonly' bit is not set exec (@sSql) end
בברכה,
חיים פישנר.
-
על הכיפק, חיים :)
נראה לי שעלית על זה.
כן, אני יודעת שהם משתמשים בסיומת BAK גם לקבצי TRN.
חשבתי בהתחלה לשנות את זה, כי זה קצת מבלבל,
אבל יש מספר לא קטן של תהליכים שמתממשקים אחד לשני ומסתמכים על זה, אז שהחלטתי שכל ה-Regresion Tests שאצטרך לעשות כדי לוודא שהכל תקין לא באמת שווים את השינוי.עם זאת, השינוי שהצעת בהחלט שווה את זה.
הג'וב הזה לא נכשל מאז, אגב, אבל אני מבסוטה לדעת את הסיבה.
תודה רבה.
ותקופת חגים טובה לכולם.
רוני (מהולנד הרחוקה)