none
תהליך שחזור DB יומי נכשל. RRS feed

  • שאלה

  • יש לי תהליך יומי שמשחזר 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 בלילה של היום החדש.

    כל הלוגים קיימים במקומם בתיקיית הגיבויים, הכל עושה רושם תקין.

    יש למישהו רעיון למה הג'וב נכשל?

    חג שמח, אגב :)

    תודה מראש,

    רוני

    יום שני 17 ספטמבר 2012 07:40

תשובות

  • היי רוני !

    טוב אז כמו שחשדתי כאשר בונים בסקריפט את פקודת השחזור עבור קבצי הלוג (בדרך כלל הסיומת שלהם היא 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


    גמר חתימה טובה!



    חיים פישנר.

    יום רביעי 26 ספטמבר 2012 18:42

כל התגובות

  • שכחתי לומר שהגרסה היא

    SQL Server 2008 SP3 Enterprise Edition.

    יום שני 17 ספטמבר 2012 08:25

  • היי רוני, חג שמח :)!

    ניראה לי שאת כבר דיי עלית על הבעיה כשאמרת ש: "כלומר, משהו התחרבש בסדר שיחזור הלוגים."

    כי הגיוני שהוא לא יצליח לגלגל קובץ גיבוי של הלוג שישן מהזמן הדיבי כבר נמצא בו....
    במקרה הראשון היה גלגול של לוגים כמו שרשמת והצגת עד-16/09 בשעה 3

    20120916_031349


    ואז "התפלק" לו לשם גיבוי לוג של יום קודם בעצם ה- 15/09 בשעה 23

    20120915_231017


    ואם נשים לב ללוג שאפילו אחרי זה היה אמור להתגלגל הוא גם לא תואם בזמן כי הוא חוזר גם כן אחורה אפילו שהוא בתאריך ה-16/09 כי הוא התבצע בשעה 00 ככל הנראה.

    20120916_001017



    בקיצור כל השאלה היא כיצד הג'וב אצלכם בונה את הפקודות RESTORE שהוא צריך לבצע ?

    האם הוא עושה את זה בצורה דינמית?

    ומהיכן הוא מחלץ את שמות הקבצים אותם הוא צריך לשחזר ?


    חיים פישנר.




    • נערך על-ידי haim fishner יום שני 17 ספטמבר 2012 13:56
    יום שני 17 ספטמבר 2012 13:55
  • שלום רוני,

    מבלי לגרוע בכל האמור לעיל, לדעתי ההודעה הנ"ל אומרת הכל:

    [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 ?

    בברכה,
    נועם

    יום רביעי 19 ספטמבר 2012 13:28
  • הי רוני,

    רוני נשמח אם תעדכני אותנו בסטטוס השאלה.

    אם אחת מן התשובות עזרה לך, אנא סמני אותה.

    תודה,

    צוות הפורומים.


    מיקרוסופט מציעה שירות זה ללא תשלום, למטרת סיוע למשתמשים והעשרת הידע הקשור בטכנולוגיות ובמוצרים של מיקרוסופט. תוכן זה מתפרסם כפי שהוא והוא אינו מעיד על כל אחריות מצד מיקרוסופט.

    יום ראשון 23 ספטמבר 2012 13:44
  • סליחה על התגובה המאוחרת, יצאתי קצת לחופש :)

    ובכן,

    להלן הג'וב שאנחנו משתמשים בו (קיים כבר זמן רב, הוקם לפני שהתחלתי לעבוד כאן)

    החלק הרלוונטי בסקריפט שקשור לשחזור לוגים הוא החלק שמתחיל בפקודה:

    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
    
    

    יום רביעי 26 ספטמבר 2012 08:13
  • היי רוני !

    טוב אז כמו שחשדתי כאשר בונים בסקריפט את פקודת השחזור עבור קבצי הלוג (בדרך כלל הסיומת שלהם היא 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


    גמר חתימה טובה!



    חיים פישנר.

    יום רביעי 26 ספטמבר 2012 18:42
  • רק להסבר אני הוספתי 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
    בברכה,


    חיים פישנר.

    יום רביעי 26 ספטמבר 2012 18:47
  • על הכיפק, חיים :)

    נראה לי שעלית על זה.

    כן, אני יודעת שהם משתמשים בסיומת BAK גם לקבצי TRN.
    חשבתי בהתחלה לשנות את זה, כי זה קצת מבלבל,
    אבל יש מספר לא קטן של תהליכים שמתממשקים אחד לשני ומסתמכים על זה, אז שהחלטתי שכל ה-Regresion Tests שאצטרך לעשות כדי לוודא שהכל תקין לא באמת שווים את השינוי.

    עם זאת, השינוי שהצעת בהחלט שווה את זה.

    הג'וב הזה לא נכשל מאז, אגב, אבל אני מבסוטה לדעת את הסיבה.

    תודה רבה.

    ותקופת חגים טובה לכולם.

    רוני (מהולנד הרחוקה)

    יום חמישי 27 ספטמבר 2012 11:27