第三篇――第二部分――第五文配置SQLServer镜像――域环境SQLServer镜像日常维护(三)

2014-11-24 09:55:53 · 作者: · 浏览: 6
LE @CurrID <= @MaxID BEGIN SELECT @DBName = DBName FROM @DBs WHERE DBID = @CurrID; SET @LogBackup = @LogBackupLocation + @DBName + '\'; -- Make sure backup location exists -- Will not overwrite existing files, if any IF @Debug = 0 BEGIN EXEC xp_create_subdir @LogBackup; END ELSE BEGIN PRINT 'Exec xp_create_subdir ' + @LogBackup + ';'; END SET @LogBackup = @LogBackup + @DBName + @DateSerial + '.' + @FileExtension SET @SQL = 'Backup Log ' + QUOTENAME(@DBName) + ' To Disk = ''' + @LogBackup + ''';'; BEGIN TRY IF @Debug = 0 BEGIN PRINT 'Backing up the log for ' + @DBName; EXEC sp_executesql @SQL; END ELSE BEGIN PRINT 'Print ''Backing up the log for ' + @DBName + ''';'; PRINT @SQL; END END TRY BEGIN CATCH SET @ErrNumber = ERROR_NUMBER(); SET @ErrSeverity = ERROR_SEVERITY(); SET @ErrState = ERROR_STATE(); SET @ErrProcedure = ERROR_PROCEDURE(); SET @ErrLine = ERROR_LINE(); SET @ErrMsg = ERROR_MESSAGE(); INSERT INTO @Failures ( DBName , ErrNumber , ErrSeverity , ErrState , ErrProcedure , ErrLine , ErrMsg ) SELECT @DBName , @ErrNumber , @ErrSeverity , @ErrState , @ErrProcedure , @ErrLine , @ErrMsg END CATCH SET @CurrID = @CurrID + 1; END IF EXISTS ( SELECT 1 FROM @Failures ) BEGIN SELECT @MaxID = MAX(FailId) , @CurrID = 1 FROM @Failures WHILE @CurrID <= @MaxID BEGIN SELECT @DBName = DBName , @ErrNumber = ErrNumber , @ErrSeverity = ErrSeverity , @ErrState = ErrState , @ErrProcedure = ErrProcedure , @ErrLine = ErrLine , @ErrMsg = ErrMsg FROM @Failures WHERE FailId = @CurrID PRINT ''; PRINT 'Database Name = ' + @DBName; PRINT 'Error Number = ' + CAST(@ErrNumber AS VARCHAR); PRINT 'Error Severity = ' + CAST(@ErrSeverity AS VARCHAR); PRINT 'Error State = ' + CAST(@ErrState AS VARCHAR); PRINT 'Error Procedure = ' + ISNULL(@ErrProcedure, ''); PRINT 'Error Line = ' + CAST(@ErrLine AS VARCHAR); PRINT 'Error Message= ' + @ErrMsg; PRINT ''; SET @CurrID = @CurrID + 1 END SELECT @FailedDBs = ISNULL(@FailedDBs + ', ', '') + QUOTENAME(DBName) FROM @Failures IF @SendAlerts = 1 AND @AlertRecipients IS NOT NULL BEGIN IF EXISTS ( SELECT 1 FROM sys.configurations WHERE name = 'Database Mail XPs' ) BEGIN SELECT TOP ( 1 ) @ProfileName = name FROM msdb.dbo.sysmail_profile P WITH ( NOLOCK ) LEFT JOIN msdb.dbo.sysmail_principalprofile PP ON PP.profile_id = P.profile_id ORDER BY PP.is_default DESC SET @Subject = 'Backup failures on ' + CAST(@@SERVERNAME AS VARCHAR(255)) SET @Body = 'Unable to back up the following databases: ' + @FailedDBs EXEC msdb..sp_send_dbmail @profile_name = @ProfileName, @recipients = @AlertRecipients, @Subject = @Subject, @body = @Body END END RAISERROR ('Unable to back up the following databases: %s', 1, 1, @FailedDBs); END

日志备份文件管理:

由于日志备份的频率较高,所以可能一段时间之后,日志文件会有很多个,即使个数不多(以追加的方式每次写入同一个文件,本人不建议这样做),日志备份的体积也可能会很大。因此,对过久的日志文件,应该进行归档或者删除。对文件的归档,可以使用sys.xp_delete_file存储过程实现。下面提供一个删除日志备份文件的脚本,同样是收集来的,使用者不要在没有大面积修改前直接以原创方式发布:

CREATE PROCEDURE dbo.dba_DeleteLogBackups

监控日志文件大小:

常规的日志备份并不能完全避免日志文件的异常增长,所以对日志文件大小的监控也是非常重要的,另外如果使用2005,确保 http://support.microsoft.com/kb/947462 这里提到的补丁已经打上。日志过大,会导致初始化过程变得很慢甚至超时,针对日志过大,首先要检查是否有常规的日志备份,其次就是检查是否有未关闭的事务并且运行了很久。

在确定日志文件已经有常规备份并且实在太大是,收缩日志文件可能是必须做的事情,但是通常收缩应该是最后一步。这里包含两个部分:

识别需要收缩的日志 收缩日志文件

识别需要收缩的日志:

这里使用脚本查询主体服务器上已经配置为镜像的库机器日志文件大小:

SELECT  DBName = DB_NAME(MF.database_id) , 
        LogFileName = MF.[name] , 
        LogFileSize = CEILING(MF.[size] * 8 / 1024.0) 
FROM    sys.master_files MF 
        INNER JOIN sys.database_mirroring DM ON DM.database_id = MF.database_id 
WHERE   MF.[type] = 1 -- 日志文件 
        AND DM.Mirroring_Role = 1--主体数据库

需要提醒一下,对主体库的日志收缩并不同步到镜像库,所以在使用DBCC SHRINKFILE之后,使用ALTER DATABASE XX MODIFY FILE强制主体库更改日志文件的大小。以便同步到镜像库。

收缩日志文件:

下面是某位MCM提供的进行收缩的脚本,这个脚本主要针对镜像库的日志收缩:
CREATE PROCEDURE dbo.dba_ShrinkMirroredDatabases 
    -- database to shrink; all mirrored databases if null 
    @DBName SYSNAME = NULL , 
    -- target size for shrink operation. Defaults to 5 GB (5120 MB) 
    @TargetSize INT = 5120 , 
    -- 0 = Execute it, 1 = Output SQL that would be executed 
    @Debug BIT = 0 
AS 
    DECLARE @CurrID INT , 
        @MaxID INT , 
        @DefaultTargetSize INT , 
        @FileName SYSNAME , 
        @FileSize INT , 
        @NewFileSize INT , 
        @SQL NVARCHAR(MAX) , 
        @ErrMsg NVARCHAR(500) 
    DECLARE @MirroredDBs TABLE 
        ( 
          MirroredDBID INT IDENTITY(1, 1) 
                           NOT NULL 
                           PRIMARY KEY , 
          DBName SYSNAME NOT NULL , 
          LogFileName SYSNAME NOT NULL , 
          FileSize INT NOT NULL 
        ) 
    SET NOCOUNT ON 
-- Assume entered as GB and convert to MB 
    IF @TargetSize < 20 
        BEGIN 
            SET @TargetSize = @TargetSize * 1024 
        END 
-- Assume entered as MB and use 512 
    ELSE 
        IF @TargetSize <= 512 
            BEGIN 
                SET @TargetSize = 512 
            END 
-- Assume entered as KB and return warning 
        ELSE 
            IF @TargetSize > 19922944 
                BEGIN 
                    SET @ErrMsg = 'Please enter a valid target size less than 20 GB. ' 
                        + 'Amount entered can be in GB (max size = 19), ' 
                        + 'MB (max size = 19456), or ' 
                        + 'KB (max size = 19922944).'; 
                    GOTO ErrComplete; 
                END 
-- Assume entered as KB and convert to MB 
            ELSE 
                IF @TargetSize > 525311 
                    BEGIN 
                        SET @TargetSize = 525311 / 1024 
                    END 
-- Assume entered as KB and use 512 as converted MB 
                ELSE 
                    IF @TargetSize > 19456 
                        BEGIN 
                            SET @TargetSize = 512 
                        END 
-- Else assume entered as MB and use as entered 
    INSERT  INTO @MirroredDBs 
            ( DBName , 
              LogFileName , 
              FileSize 
            ) 
            SELECT  DB_NAME(MF.database_id) , 
                    MF.[name] , 
       -- Size = number of 8K pages 
                    CEILING(MF.[size] * 8 / 1024.0) 
            FROM    sys.master_files MF 
                    INNER JOIN sys.database_mirroring DM ON DM.database_id = MF.database_id 
            WHERE   MF.[type] = 1 
                    AND -- log file 
                    DM.Mirroring_Role = 1 
                    AND -- Principal partner 
      -- Specified database or all databases if null 
                    ( MF.database_id = @DBName 
                      OR @DBName IS NULL 
                    ) 
    IF NOT EXISTS ( SELECT  1 
                    FROM    @MirroredDBs ) 
        BEGIN 
            SET @ErrMsg = CASE WHEN @DBName IS NOT NULL 
                               THEN 'Database ' + QUOTENAME(@DBName) 
                                    + ' was either not found or is not' 
                                    + ' a mirroring principal.' 
                               ELSE 'No databases were found in the ' 
                                    + 'mirroring principal role.' 
                          END; 
            GOTO ErrComplete; 
        END 
    ELSE 
        BEGIN 
            SELECT  @MaxID = MAX(MirroredDBID) , 
                    @CurrID = 1 
            FROM    @MirroredDBs 
            WHILE @CurrID <= @MaxID 
                BEGIN 
                    SELECT  @DBName = DBName , 
                            @FileName = LogFileName , 
                            @FileSize = FileSize 
                    FROM    @MirroredDBs 
                    WHERE   MirroredDBID = @CurrID 
                    IF @FileSize > @TargetSize 
                        BEGIN 
                            SET @SQL = 'Use ' + QUOTENAME(@DBName) + ';' 
                                + 'DBCC ShrinkFile(''' + @FileName + ''', ' 
                                + CAST(@TargetSize AS NVARCHAR) + ');' 
                            IF @Debug = 0 
                                BEGIN 
                                    EXEC sp_executesql @SQL 
                                END 
                            ELSE 
                                BEGIN 
                                    PRINT @SQL 
                                END 
                            SELECT -- Size = number of 8K pag