第二部分:SQL Server镜像日常维护:
如果你搭建好高可用方案就觉得已经完事的话,后果将非常严重。所以本文重点介绍常规的镜像维护,记住维护工作极其重要。
维护工作主要包含下面几个部分:
事务日志备份 监控日志文件大小 SQL Server常规升级 故障转移后恢复原有主体服务器 数据库配置 控制故障转移 自动故障转移事务日志备份:
镜像的核心思想就是对事务日志的操作,这也是镜像必须使用完整恢复模式的原因之一。抛开高可用,任何完整模式下的数据库如果缺乏维护,日志文件都会出现非预期增长,最终导致数据库变成只读。根据拇指定律,核心系统的日志备份监控不宜大于半个小时。如果事务量巨大,甚至需要把备份间隔缩短到15分钟。对于事务日志的管理,很重要的一个工作是做常规的日志备份,日志备份可以用维护计划实现,也可以写脚本实现,更多信息可以看《SQL Server扫盲》系列的日志备份一文:http://blog.csdn.net/dba_huangzj/article/details/26844859 。这里简要演示一下脚本备份的操作。
脚本化日志备份:
脚本的核心主要有下面几个:检查数据库状态:对于镜像环境中的镜像角色,是不能联机的,也就是不能进行备份(包括日志备份)。所以如果要做备份脚本,需要检查数据库状态,可以查看sys.database_mirroring和sys.databases中的state/state_desc。 检查恢复模式:简单模式下不允许进行事务日志备份,所以需要检查sys.databases中的recovery_model/recovery_model_desc的信息。 检查数据库快照:对于数据库快照,同样不能使用备份操作,所以备份时需要检查sys.databases中的source_database_id,如果不为null,则证明为快照库,跳过备份操作。 检查日志传送:对部署了日志传送的数据库进行日志备份会破坏这个功能,所以需要检查msdb中的dbo.log_shipping_primary_databases表是否存在要备份的数据库。 检查系统库:tempdb和master库不能进行日志备份,而model库也通常没有必要进行日志备份,对于msdb,视乎使用情况决定,如果搭建了复制,会出现distribution库,这个库有时候会产生很多的日志,必要时候也应该纳入备份策略中。
下面是从网上专家脚本中收集的脚本,读者如有必要,可以使用,并且进行适当修改,但是作为尊重,请勿以原创发布,除非你做了大面积的修改:
CREATE PROCEDURE dbo.dba_BackupDBLogs
-- Database name or null for all databases
@DBName SYSNAME = NULL ,
-- Location where you want the backups
@LogBackupLocation NVARCHAR(255) = NULL ,
-- log backup extension
@FileExtension NVARCHAR(3) = 'trn' ,
-- 0 = do not send alerts, 1 = send alerts
@SendAlerts BIT = 0 ,
@AlertRecipients VARCHAR(500) = NULL ,
-- 0 = execute log backup, 1 = output the code without executing
@Debug BIT = 0
AS
DECLARE @BakDir NVARCHAR(255) ,
@Exists INT ,
@CurrID INT ,
@MaxID INT ,
@SQL NVARCHAR(1000) ,
@LogBackup NVARCHAR(500) ,
@DateSerial NVARCHAR(35) ,
@ErrNumber INT ,
@ErrSeverity INT ,
@ErrState INT ,
@ErrProcedure SYSNAME ,
@ErrLine INT ,
@ErrMsg NVARCHAR(2048) ,
@FailedDBs NVARCHAR(4000) ,
@Subject VARCHAR(255) ,
@Body VARCHAR(8000) ,
@ProfileName SYSNAME
DECLARE @DBs TABLE
(
DBID INT IDENTITY(1, 1)
NOT NULL
PRIMARY KEY ,
DBName SYSNAME NOT NULL
)
DECLARE @FileExists TABLE
(
FileExists INT NOT NULL ,
FileIsDirectory INT NOT NULL ,
ParentDirectoryExists INT NOT NULL
)
DECLARE @Failures TABLE
(
FailId INT IDENTITY(1, 1)
NOT NULL
PRIMARY KEY ,
DBName SYSNAME NOT NULL ,
ErrNumber INT NULL ,
ErrSeverity INT NULL ,
ErrState INT NULL ,
ErrProcedure SYSNAME NULL ,
ErrLine INT NULL ,
ErrMsg NVARCHAR(2048) NULL
)
SET NOCOUNT ON
SET @DateSerial = CONVERT(NVARCHAR, GETDATE(), 112)
+ REPLACE(CONVERT(NVARCHAR, GETDATE(), 108), ':', '')
IF @DBName IS NOT NULL
BEGIN
IF NOT EXISTS ( SELECT 1
FROM sys.databases
WHERE name = @DBName )
BEGIN
RAISERROR ('The specified database [%s] does not exist.
Please check the name entered or do not supply
a database name if you want to back up the log
for all online databases using the full or
bulk-logged recovery model.', 16, 1, @DBName);
RETURN;
END
IF EXISTS ( SELECT 1
FROM sys.databases
WHERE name = @DBName
AND state > 0 )
BEGIN
RAISERROR ('The specified database [%s] is not online.
Please check the name entered or do not supply
a database name if you want to back up the log
for all online databases using the full or
bulk-logged recovery m