准备:

1. 一个主机,两个虚拟机

2. 安装相同版本的SQL Server(2016及以上,Standard或Enterprise)>参考

3. 防火墙开放端口5022

一、数据库备份和还原

--主体:设置“完整恢复模式”
USE master;
ALTER DATABASE [DBName] SET RECOVERY FULL  
GO
 
--主体:备份数据库 
USE master;
BACKUP DATABASE [DBName]
   TO DISK='G:\SQLServer\BACKUP\DBName.bak'   
   WITH INIT,FORMAT;  
GO  
 
--镜像:还原数据库(NORECOVERY)
--若主体数据库与镜像数据库路径一致
RESTORE DATABASE DBName   
    FROM DISK = 'C:\DBName.bak'   
    WITH NORECOVERY  
GO
--若不一致
RESTORE DATABASE [DBName]
   FROM DISK='C:\DBName.bak'  
   WITH NORECOVERY,   
      MOVE 'DBName_Data' TO   
         'D:\Program Files\Microsoft SQL Server\MSSQL.n\MSSQL\Data\DBName_Data.mdf',   
      MOVE 'DBName_Log' TO  
         'D:\Program Files\Microsoft SQL Server\MSSQL.n\MSSQL\Data\DBName_Log.ldf';  
GO

主体与镜像数据库路径不一致时,建议先使用命令行查询实际的逻辑名称(LogicalName):

RESTORE FILELISTONLY FROM DISK='C:\DBName.bak' 

比如我的数据库数据逻辑名是DBName而非DBName_Data,日志的逻辑名是DBName_log而不是DBName_Log

二、创建证书并交换

/*主体 HOST_A*/
--创建数据库主密钥
CREATE MASTER KEY ENCRYPTION BY PASSWORD = '<1_Strong_Password!>';  
GO
--创建证书
USE master;  
CREATE CERTIFICATE HOST_A_cert   
WITH SUBJECT = 'HOST_A certificate for database mirroring',   
EXPIRY_DATE = '12/31/2020';  
GO
--备份证书
BACKUP CERTIFICATE HOST_A_cert TO FILE = 'C:\HOST_A_cert.cer';  
GO   


/*镜像 HOST_B*/
--创建数据库主密钥(可选)
CREATE MASTER KEY ENCRYPTION BY PASSWORD = '<Strong_Password_#2>';  
GO  
--创建证书
CREATE CERTIFICATE HOST_B_cert   
   WITH SUBJECT = 'HOST_B certificate for database mirroring',   
   EXPIRY_DATE = '12/31/2020';  
GO  
--备份证书
BACKUP CERTIFICATE HOST_B_cert TO FILE = 'C:\HOST_B_cert.cer';  
GO   


/*见证 HOST_C*/
--创建证书
CREATE CERTIFICATE HOST_C_cert   
   WITH SUBJECT = 'HOST_C certificate for database witness',   
   EXPIRY_DATE = '12/31/2020';  
GO  
--备份证书
BACKUP CERTIFICATE HOST_C_cert TO FILE = 'C:\HOST_C_cert.cer';  
GO   


/*交换证书:相互拷贝证书*/

三、创建数据库镜像端点(用于出站连接)

/*主体*/
USE master;
CREATE ENDPOINT Endpoint_Mirroring  
   STATE = STARTED  
   AS TCP (  
      LISTENER_PORT=5022
      , LISTENER_IP = ALL  
   )   
   FOR DATABASE_MIRRORING (   
      AUTHENTICATION = CERTIFICATE HOST_A_cert  
      , ENCRYPTION = REQUIRED ALGORITHM AES  
      , ROLE = ALL  
   );  
GO

/*镜像*/
USE master;
CREATE ENDPOINT Endpoint_Mirroring  
   STATE = STARTED  
   AS TCP (  
      LISTENER_PORT=5022
      , LISTENER_IP = ALL  
   )   
   FOR DATABASE_MIRRORING (   
      AUTHENTICATION = CERTIFICATE HOST_B_cert  
      , ENCRYPTION = REQUIRED ALGORITHM AES  
      , ROLE = ALL  
   );  
GO

/*见证*/
USE master;
CREATE ENDPOINT Endpoint_Mirroring  
   STATE = STARTED  
   AS TCP (  
      LISTENER_PORT=5022
      , LISTENER_IP = ALL  
   )   
   FOR DATABASE_MIRRORING (   
      AUTHENTICATION = CERTIFICATE HOST_C_cert  
      , ENCRYPTION = REQUIRED ALGORITHM AES  
      , ROLE = WITNESS  
   );  
GO

四、还原证书(用于入站连接)

/* 主体 */
USE master;
--1.为HOST_B/HOST_C创建登录名
CREATE LOGIN Mirror_login   
   WITH PASSWORD = '1Sample_Strong_Password!@#';  
GO
--2.创建一个使用该登录名的用户
USE master;  
CREATE USER Mirror_user FOR LOGIN Mirror_login;  
GO
--3.将HOST_B的证书与它在HOST_A上的用户关联
CREATE CERTIFICATE HOST_B_cert
AUTHORIZATION Mirror_user 
FROM FILE = 'C:\HOST_B_cert.cer';  
GO
--3.将HOST_C的证书与它在HOST_A上的用户关联  
CREATE CERTIFICATE HOST_C_cert 
AUTHORIZATION Mirror_user 
FROM FILE = 'C:\HOST_C_cert.cer';  
GO  

/* 镜像 */
--TODO:创建登录名及用户
USE master;  
CREATE CERTIFICATE HOST_A_cert  
AUTHORIZATION Mirror_user 
FROM FILE = 'C:\HOST_A_cert.cer';  
GO   
CREATE CERTIFICATE HOST_C_cert  
AUTHORIZATION Mirror_user 
FROM FILE = 'C:\HOST_C_cert.cer';  
GO  

/* 见证 */
--TODO:创建登录名及用户
USE master;
CREATE CERTIFICATE HOST_A_cert  
AUTHORIZATION Mirror_user 
FROM FILE = 'C:\HOST_A_cert.cer';  
GO   
CREATE CERTIFICATE HOST_B_cert  
AUTHORIZATION Mirror_user 
FROM FILE = 'C:\HOST_B_cert.cer';  
GO

五、开始镜像

/*镜像*/
USE master  
GO  
ALTER DATABASE [DBName] SET PARTNER = 'TCP://192.168.16.218:5022';  --配置主体服务器
GO  

/*主体*/
USE master  
GO  
ALTER DATABASE [DBName] SET PARTNER = 'TCP://192.168.16.159:5022';  --配置镜像服务器
GO  
ALTER DATABASE [DBName] SET WITNESS = 'TCP://192.168.16.153:5022';  --配置见证服务器
GO  

--注意:先配置镜像的PARTNER,再配置主体的

问题

在配置过程中,由于误操作比较多,导致遇到LSN过早的问题,如果在当前业务中日志不是很重要,可以先把日志清空再进行备份和还原操作

/*主体*/
--清除日志
USE [master]
GO
ALTER DATABASE DBName SET RECOVERY SIMPLE WITH NO_WAIT
GO
ALTER DATABASE DBName SET RECOVERY SIMPLE   --简单模式
GO
USE MirrorDemo
GO
DBCC SHRINKFILE (N'DBName_log' , 2, TRUNCATEONLY)  --设置压缩后的日志大小为2M,可以自行指定
GO
USE [master]
GO
ALTER DATABASE DBName SET RECOVERY FULL WITH NO_WAIT
GO
ALTER DATABASE DBName SET RECOVERY FULL  --还原为完全模式
GO
--备份日志:参照第一步

/*镜像*/
--还原日志:参照第一步

附两个镜像配置教程以供参考:

  • SQLServer 数据库镜像(二)域环境中完整镜像脚本配置
  • 使用安全向导配置SQL Server镜像