脚本分享:别人家的镜像自动化部署

 

脚本1:

 

实例名:

主服务器:X

镜像服务器:Y

 

步骤:

1. 在主服务器和镜像服务器之间创建链接服务器,配置为使用RPC(Remote procedure call)调用,为了执行SP。

例如:lnk_X_Y_mirroring(链接服务器名)

2. 在主服务器上创建以下SP。

3. 根据需要使用作业每30分钟或1小时调用SP(usp_Mirroring_Configuration)。

4. 一旦一个新数据库创建,镜像会通过作业的执行被部署。

5. 将触发“Mirroring Configuration”为名的告警,内容为“Mirroring Configured for db_55555 and safety level is OFF”

 

/*******************************************************************************
DESCRIPTION: Automatic Mirroring_Configuration for new databases
AUTHOR: Vasan
DATE WRITTEN: 17 MARCH 2015
Automatic Mirroring configuration for newly created user databases:
-------------------------------------------------------------------
Instance names:
---------------
Principle server : X
Mirroring Server : Y
Steps to follow:
1. Create link server between principle server and mirror server with RPC (Remote procedure call) set as true in order to execute the procedure.
Eg : lnk_X_Y_mirroring (Link server name)
2. Create below stored procedure in to principle server.
3. Schedule this Stored procedure (usp_Mirroring_Configuration) with 30mins/1hr interval via job
4. Once the new database created in server mirroring will be configure.
5. Alert will be trigger with the subject anme of Mirroring Configuration
Mail contect:“Mirroring Configured for db_55555 and safety level is OFF”
*******************************************************************************/
Begin
SET NOCOUNT ON;
IF OBJECT_ID(N'tempdb..##tbl_new_databases') IS NOT NULL
BEGIN
DROP TABLE ##tbl_new_databases
END
Declare @dbname nvarchar(max)
Declare @Path nvarchar(500)
Declare @todiskbkp nvarchar(max)
Declare @todisklogbkp nvarchar(max)
Declare @SQL nvarchar(max)
Declare @count SMALLINT
Declare @SQLpartnerprimary nvarchar(max)
Declare @SQLmirror nvarchar(max)
Declare @Mirrorsaftey nvarchar(max)
-- Restore Part Variables
Declare @RestorePath nvarchar(500)
Declare @fromdiskbkp nvarchar(max)
Declare @fromdisklogbkp nvarchar(max)
Declare @SQLrestore nvarchar(max)
Declare @SQLpartnermirror nvarchar(max)
--Mail Part
DECLARE @tableHTML NVARCHAR(MAX) ;
DECLARE @bodyMsg nvarchar(max)
DECLARE @subject nvarchar(max)
SELECT A.name into ##tbl_new_databases
FROM
sys.databases A INNER JOIN sys.database_mirroring B
ON A.database_id=B.database_id
WHERE a.database_id > 4 and B.mirroring_state is NULL and A.is_read_only=0 and state_desc='ONLINE'
if (Select COUNT(*) from ##tbl_new_databases)>0
Begin
DECLARE DB CURSOR FOR
-- Fetching newly created database to configure mirroring
Select name from ##tbl_new_databases
OPEN DB
FETCH NEXT FROM DB INTO @dbname
WHILE @@FETCH_STATUS=0
BEGIN
-- changing recovery model from Simple to Full for new database since new database created with simple recovery model
set @sql= 'if (SELECT recovery_model_desc FROM sys.databases where name = '''+@dbname+''' ) = ''SIMPLE''
begin
Use master
ALTER DATABASE '+@dbname+' SET RECOVERY FULL WITH NO_WAIT
end'
--print @sql
EXEC master.dbo.sp_executesql @SQL
-- Setting Backup folder path for primary server
--(Backup should be placed some common path or with in mirror server for easy recovery process) here i chose mirror server local drive
Set @dbname=@dbname
Set @Path='\\Mirror Server Name (Y)\d$\backup\'+@dbname
set @todiskbkp=@Path+'\'+@dbname+'_'+ replace(CONVERT(VARCHAR(11),GETDATE(),106),' ','')+'.bak'
set @todisklogbkp=@Path+'\'+@dbname+'_'+ replace(CONVERT(VARCHAR(11),GETDATE(),106),' ','')+'.trn'
-- Creating new backup folder for new db in Mirror server
EXEC master.dbo.xp_create_subdir @Path
--Create Database Backups for new db
set @SQL= '
BACKUP DATABASE ' +@dbname+'
TO DISK = '''+@todiskbkp+'''
WITH FORMAT;
BACKUP LOG ' +@dbname+'
TO DISK ='''+@todisklogbkp+'''
WITH FORMAT;
'
--Print @SQL
EXEC master.dbo.sp_executesql @SQL
--Restoring the new dataabse to Mirror server
-- Setting Restor path for mirror server
Set @RestorePath='D:\backup\'+@dbname
set @fromdiskbkp=@RestorePath+'\'+@dbname+'_'+ replace(CONVERT(VARCHAR(11),GETDATE(),106),' ','')+'.bak'
set @fromdisklogbkp=@RestorePath+'\'+@dbname+'_'+ replace(CONVERT(VARCHAR(11),GETDATE(),106),' ','')+'.trn'
--Create the Mirror Database (restoring the new database backup into mirror server)
set @SQLrestore='
RESTORE DATABASE '+@dbname+' FROM DISK = N'''+@fromdiskbkp+''' WITH FILE = 1,
MOVE N'''+@dbname+''' TO N''D:\data\'+@dbname+'.mdf'',
MOVE N'''+@dbname+'_log'' TO N''D:\log\'+@dbname+'.LDF'',
NORECOVERY, NOUNLOAD, REPLACE, STATS = 10
RESTORE LOG '+@dbname+' FROM DISK = N'''+@fromdisklogbkp+'''
WITH FILE = 1, NORECOVERY, NOUNLOAD, STATS = 10
'
--print @SQLrestore
EXEC lnk_X_Y_mirroring.master.dbo.sp_executesql @SQLrestore
--Listener Port on mirror server
set @SQLpartnermirror= '
ALTER DATABASE '+@dbname+'
SET PARTNER=''tcp://Domain Name:Port Number'';
'
--print @SQLpartnermirror
EXEC lnk_X_Y_mirroring.master.dbo.sp_executesql @SQLpartnermirror
--Listener Port on principal server
set @SQLpartnerprimary='
ALTER DATABASE '+@dbname+'
SET PARTNER=''tcp://Domain Name:Port Number'';'
EXEC master.dbo.sp_executesql @SQLpartnerprimary
--Print @SQLpartnerprimary
--Set Mirroring Operating Mode to “High Performance”
set @Mirrorsaftey='
ALTER DATABASE '+@dbname+' SET SAFETY OFF
'
--print @SQLpartnermirror
EXEC master.dbo.sp_executesql @Mirrorsaftey
FETCH NEXT FROM DB INTO @DBNAME
END
CLOSE DB
DEALLOCATE DB
EXEC msdb.dbo.sp_send_dbmail
@profile_name = 'DBAProfile',
@recipients = '[email protected]',
@subject = 'Mirroring Configuration',
@query='set nocount on SELECT ''Mirroring Configured for ''+ A.name +'' and safety level is ''+ B.[mirroring_safety_level_desc] COLLATE Latin1_General_CI_AI
FROM
sys.databases A
INNER JOIN sys.database_mirroring B
ON A.database_id=B.database_id
WHERE a.database_id > 4 AND A.name in (Select name from ##tbl_new_databases)',
@query_result_no_padding =0,
@query_result_width = 32767,
@query_no_truncate = 1,
@attach_query_result_as_file = 0,
@Body_format = 'text' ,
@append_query_error = 1
Drop table ##tbl_new_databases
END
END

 

 

脚本2:

 

准备步骤:

1. 安装和一个辅助SQL Server实例(版本、补丁和LICENSE类型跟主服务器实例一样)。

2. SQL Server连接启用TCP/IP协议。

3. 为备份和恢复操作配置网络共享,类似\\dfsroot\sqlbackup

4. 允许使用xp_cmdshell扩展存储过程。


仅通过一个触发器访问执行所有的操作是不行的。这个方法包含四个组件:1个事件接收器表,1个工作负载存储过程,1个DDL触发器和1个以一定间隔执行之前提到的存储过程的SQL Server代理作业。

 

步骤1:创建1个事件接收器表

该表将会保存CREATE数据库动作发生时的名字和SQL事件。事件类型不重要,我们只对数据库名感兴趣。

USE [master]
GO
/****** Object: Table [dbo].[new_db_table] Script Date: 05/19/2008 15:26:56 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[new_db_table](
[name] [nvarchar](100) NULL,
[event] [nvarchar](100) NULL
) ON [PRIMARY]

 

步骤2:创建自动化存储过程

这是主要的脚本,用于检查动作表,执行备份初始化。在SQL Server 2005,对于附加数据库动作是没有数据库事件的,即便事实上它是一个CREATE_DATABASE事件。在SQL Server 2008解决了,导致触发器对于ATTACH和CREATE动作,在动作表都添加一个条目。

USE [master]
GO
/****** Object: StoredProcedure [dbo].[sp_auto_mirror_config] Script Date: 07/10/2008 10:56:15 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
— ============================================================================
— Author: 
— Create date: <4/9/2008>
— Description: 
— Syntax: 
— =============================================================================
CREATE proc [dbo].[sp_auto_mirror_config]
as
declare @dbname sysname, @bckstmt nvarchar(500), @cmd varchar(250), @bupath varchar(100)
declare @mirrorsp nvarchar(100), @mirrorsql nvarchar(500), @altersql nvarchar(250)
declare @primarysrvr nvarchar(50), @mirrorsrvr nvarchar(50), @witnes***vr nvarchar(50), @domain nvarchar(50)
–set your sql server and backup paths here
set @bupath = ‘\\sql1\sqlbackup’
set @primarysrvr = ‘sql1’
set @mirrorsrvr = ‘sql2’
set @domain = ‘.staging.local’
set @witnes***vr = ‘smres2’
set @mirrorsp = @mirrorsrvr + ‘.master.dbo.sp_executesql ‘
begin
if (select count(*) from new_db_table where event = ‘CREATE_DATABASE’) > 0
begin
create table #userdbs (name sysname)
insert into #userdbs select name from new_db_table
declare cdb cursor for select name from #userdbs
open cdb
fetch cdb into @dbname
while @@fetch_status = 0
begin
–Check to make sure that Auto_Close and Auto_Shrink DB Properties are correct and that Recovery is Full
set @altersql = ‘alter database ‘ + char(91) + @dbname + char(93) + ‘ set AUTO_CLOSE off’
exec (@altersql)
set @altersql = ‘alter database ‘ + char(91) + @dbname + char(93) + ‘ set AUTO_SHRINK on’
exec (@altersql)
set @altersql = ‘alter database ‘ + char(91) + @dbname + char(93) + ‘ set RECOVERY full’
exec (@altersql)
–perform initial database backup
set @bckstmt = ‘backup database ‘ + char(91) + @dbname + char(93)+ ‘ to ‘ +
‘disk = N’ + char(39) + @bupath + ‘\’ + @dbname + ‘.bak’ + char(39)
exec (@bckstmt)
–perform initial database log backup
set @bckstmt = ‘backUp log ‘ + char(91) + @dbname + char(93)+ ‘ to ‘ +
‘disk = N’ + char(39) + @bupath + ‘\’ + @dbname + ‘_log.bak’ + char(39)
exec (@bckstmt)
–perform database restore on linked remote mirror sql server
set @bckstmt = ‘restore database ‘ + char(91) + @dbname + char(93) + ‘ from ‘ +
‘Disk = N’ + char(39) + @bupath + ‘\’ + @dbname + ‘.bak’ + char(39) + ‘ with norecovery, replace’
exec @mirrorsp @bckstmt
–perform database log restore on linked remote mirror sql server
set @bckstmt = ‘restore log ‘ + char(91) + @dbname + char(93) + ‘ from ‘ +
‘Disk = N’ + char(39) + @bupath + ‘\’ + @dbname + ‘_log.bak’ + char(39) + ‘ with norecovery, replace’
exec @mirrorsp @bckstmt
–Initiate the mirroring on The Mirror server:
set @mirrorsql = ‘alter database ‘ + char(91) + @dbname + char(93) + ‘ set partner= N’+ char(39) + ‘TCP://’ + @primarysrvr + @domain + ‘:5022’ + char(39)
exec @mirrorsp @mirrorsql
–Initiate the mirroring on The Primary server:
set @mirrorsql = ‘alter database ‘ + char(91) + @dbname + char(93) + ‘ set partner= N’+ char(39) + ‘TCP://’ + @mirrorsrvr + @domain + ‘:5022’ + char(39)
exec (@mirrorsql)
–Enable the mirroring session on the Witness server:
set @mirrorsql = ‘alter database ‘ + char(91) + @dbname + char(93) + ‘ set witness= N’+ char(39) + ‘TCP://’ + @witnes***vr + @domain + ‘:5022’ + char(39)
exec (@mirrorsql)
–cleanup
delete from new_db_table where name = @dbname
set @cmd = ‘del ‘ + @bupath + ‘\’ + @dbname + ‘.bak’
exec xp_cmdshell @cmd
set @cmd = ‘del ‘ + @bupath + ‘\’ + @dbname + ‘_log.bak’
exec xp_cmdshell @cmd
fetch cdb into @dbname
end
close cdb
deallocate cdb
drop table #userdbs
end
end

 

步骤3:创建触发器

当匹配CREATE_DATABASE的事件发生时,它将触发,将数据库名写入事件接收器表。

/****** Object: DdlTrigger [trg_MirrorDDL] Script Date: 05/19/2008 15:31:55 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TRIGGER [trg_MirrorDDL]
ON ALL SERVER
FOR CREATE_DATABASE
AS
BEGIN
SET NOCOUNT ON;
DECLARE @data XML;
DECLARE @eventType sysname;
DECLARE @dbname varchar(100);
DECLARE @mirrorsql varchar(500);
SET @data = EVENTDATA();
SET @eventType = @data.value(‘(/EVENT_INSTANCE/EventType)[1]’, ‘sysname’);
SET @dbname = @data.value(‘(/EVENT_INSTANCE/ DatabaseName)[1]’, ‘sysname’);
–Add to new_db_table
Insert new_db_table(name,event) select @dbname,@eventType where not exists (select * from new_db_table where name = @dbname);
END
GO
SET ANSI_NULLS OFF
GO
SET QUOTED_IDENTIFIER OFF
GO
ENABLE TRIGGER [trg_MirrorDDL] ON ALL SERVER

 

步骤4:创建SQL Server代理作业

这个作业主要的目的是监控事件接收器表的新增条目。我原本想在事件接收器表上用一个触发器,但是你可能不想自动化,而是想通过作业来按需调度存储过程的执行可能会更好。

USE [msdb]
GO
/****** Object: Job [Mirroring Agent] Script Date: 05/19/2008 15:32:54 ******/
BEGIN TRANSACTION
DECLARE @ReturnCode INT
SELECT @ReturnCode = 0
/****** Object: JobCategory [[Uncategorized (Local)]]] Script Date: 05/19/2008 15:32:54 ******/
IF NOT EXISTS (SELECT name FROM msdb.dbo.syscategories WHERE name=N'[Uncategorized (Local)]’ AND category_class=1)
BEGIN
EXEC @ReturnCode = msdb.dbo.sp_add_category @class=N’JOB’, @type=N’LOCAL’, @name=N'[Uncategorized (Local)]’
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
END
DECLARE @jobId BINARY(16)
EXEC @ReturnCode = msdb.dbo.sp_add_job @job_name=N’Mirroring Agent’,
@enabled=1,
@notify_level_eventlog=2,
@notify_level_email=0,
@notify_level_netsend=0,
@notify_level_page=0,
@delete_level=0,
@description=N’No description available.’,
@category_name=N'[Uncategorized (Local)]’,
@owner_login_name=N’SMNET\administrator’, @job_id = @jobId OUTPUT
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
/****** Object: Step [Run Mirroring Stored Procedure] Script Date: 05/19/2008 15:32:55 ******/
EXEC @ReturnCode = msdb.dbo.sp_add_jobstep @job_id=@jobId, @step_name=N’Run Mirroring Stored Procedure’,
@step_id=1,
@cmdexec_success_code=0,
@on_success_action=1,
@on_success_step_id=0,
@on_fail_action=2,
@on_fail_step_id=0,
@retry_attempts=0,
@retry_interval=0,
@os_run_priority=0, @subsystem=N’TSQL’,
@command=N’USE [master]
GO
DECLARE @return_value int
EXEC @return_value = [dbo].[sp_auto_mirror_config]
SELECT ”Return Value” = @return_value
GO’,
@database_name=N’master’,
@flags=4
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
EXEC @ReturnCode = msdb.dbo.sp_update_job @job_id = @jobId, @start_step_id = 1
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
EXEC @ReturnCode = msdb.dbo.sp_add_jobschedule @job_id=@jobId, @name=N’Mirror Agent Schedule’,
@enabled=1,
@freq_type=4,
@freq_interval=1,
@freq_subday_type=4,
@freq_subday_interval=5,
@freq_relative_interval=0,
@freq_recurrence_factor=0,
@active_start_date=20080410,
@active_end_date=99991231,
@active_start_time=0,
@active_end_time=235959
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
EXEC @ReturnCode = msdb.dbo.sp_add_jobserver @job_id = @jobId, @server_name = N'(local)’
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
COMMIT TRANSACTION
GOTO EndSave
QuitWithRollback:
IF (@@TRANCOUNT > 0) ROLLBACK TRANSACTION
EndSave:

 

后记:

这两个脚本都是将数据直接备份到远程UNC路径。笔者之前在Bash下写过镜像自动化部署,日志传送自动化部署、检查和切换的脚本,数据传输用的winscp.exe,思路也就是把这些核心SQL封装调用。

 

参考:

http://www.sqlservercentral.com/scripts/Mirroring/132938/

https://jeffsani.wordpress.com/2009/03/17/how-to-automate-sql-mirroring/