转载自:http://kb.cnblogs.com/page/45937/ 最初在为公司设计SQLServer数据库镜像的时候,首先考虑的是高可用性(三台计算机,一台见证服务器,一台作主数据库,一台作镜像) 在虚拟机环境下部署成功,一切都是那么的完美。故障转移3秒以内就能够顺利完成。 1.高可用性的实施代码: /******************************************************** 此脚本在主体服务器执行 ********************************************************/ --镜像只支持彻底恢复模式,在备份数据库以前检查恢复的模式 --对要镜像的数据库进行完整备份后,复制到镜像数据库以NORECOVERNY选项进行恢复 USE master; --DROP MASTER KEY CREATE MASTER KEY ENCRYPTION BY PASSWORD = 'P@ssw0rd0'; GO --为此服务器实例制做一个证书。 --DROP CERTIFICATE HOST_A_cert CREATE CERTIFICATE HOST_A_cert WITH SUBJECT = 'HOST_A certificate',START_DATE = '01/01/2012',EXPIRY_DATE ='01/01/2020'; GO 设置上开始日期,证书有效期为一年。不设开始日期,即日启算有效期也为一年。为了不麻烦,使用上述参数设置有效期,不然任期内你会很惨。。。。。。EXPIRY_DATE ='01/01/2020'有效期到2020年,这个必定要有 --使用该证书为服务器实例建立一个镜像端点。 --DROP ENDPOINT Endpoint_Mirroring 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 = PARTNER ); GO --备份 HOST_A 证书,并将其复制到其余机器,将 C:\backup\HOST_A_cert.cer 复制到 HOST_B\HOST_C。 BACKUP CERTIFICATE HOST_A_cert TO FILE = 'C:\backup\HOST_A_cert.cer'; GO --为入站链接配置 Host_A --在 HOST_A 上为 HOST_B 建立一个登陆名。 USE master; --DROP LOGIN HOST_B_login CREATE LOGIN HOST_B_login WITH PASSWORD = 'P@ssw0rd0'; GO --建立一个使用该登陆名的用户。 --DROP USER HOST_B_user CREATE USER HOST_B_user FOR LOGIN HOST_B_login; GO --使证书与该用户关联。 --DROP CERTIFICATE HOST_B_cert CREATE CERTIFICATE HOST_B_cert AUTHORIZATION HOST_B_user FROM FILE = C:\backup\HOST_B_cert.cer' GO --授予对远程镜像端点的登陆名的 CONNECT 权限。 GRANT CONNECT ON ENDPOINT::Endpoint_Mirroring TO [HOST_B_login]; GO --在 HOST_A 上为 HOST_C 建立一个登陆名。 USE master; --DROP LOGIN HOST_C_login CREATE LOGIN HOST_C_login WITH PASSWORD = 'P@ssw0rd0'; GO --建立一个使用该登陆名的用户。 --DROP USER HOST_C_user CREATE USER HOST_C_user FOR LOGIN HOST_C_login; GO --使证书与该用户关联。 --DROP CERTIFICATE HOST_C_cert CREATE CERTIFICATE HOST_C_cert AUTHORIZATION HOST_C_user FROM FILE = C:\backup\HOST_C_cert.cer' GO --授予对远程镜像端点的登陆名的 CONNECT 权限。 GRANT CONNECT ON ENDPOINT::Endpoint_Mirroring TO [HOST_C_login]; GO USE master; --DROP LOGIN HOST_A_login CREATE LOGIN HOST_A_login WITH PASSWORD = 'P@ssw0rd0'; GO --建立一个使用该登陆名的用户。 --DROP USER HOST_A_user CREATE USER HOST_A_user FOR CERTIFICATE HOST_A_cert; GO --授予对远程镜像端点的登陆名的 CONNECT 权限。 GRANT CONNECT ON ENDPOINT::Endpoint_Mirroring TO [HOST_A_login]; GO --必需要在镜像数据库中先设置好伙伴后,才能在主体服务器执行 --在 HOST_A 的主体服务器实例上,将 HOST_B 上的服务器实例设置为伙伴(使其成为初始镜像服务器实例)。 ALTER DATABASE crm SET PARTNER = 'TCP://192.168.1.205:5022'; GO --设置见证服务器 ALTER DATABASE crm SET WITNESS = N'TCP://192.168.1.204:5022'; GO /*********************************************** 在镜像服务器执行此脚本 ***********************************************/ USE master; --DROP MASTER KEY CREATE MASTER KEY ENCRYPTION BY PASSWORD = 'P@ssw0rd0'; GO --为 HOST_B 服务器实例制做一个证书。 --DROP CERTIFICATE HOST_B_cert CREATE CERTIFICATE HOST_B_cert WITH SUBJECT = 'HOST_B certificate for database mirroring', START_DATE = '01/01/2012',EXPIRY_DATE ='01/01/2020'; ; GO --在 HOST_B 中为服务器实例建立一个镜像端点。 --DROP ENDPOINT Endpoint_Mirroring 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 = PARTNER ); GO --备份 HOST_B 证书,将 C:\HOST_B_cert.cer 复制到 HOST_A\HOST_C。 BACKUP CERTIFICATE HOST_B_cert TO FILE = 'c:\backup\HOST_B_cert.cer'; GO --为入站链接配置 Host_B --在 HOST_B 上为 HOST_A 建立一个登陆名。 USE master; --DROP LOGIN HOST_A_login CREATE LOGIN HOST_A_login WITH PASSWORD = 'P@ssw0rd0'; GO --建立一个使用该登陆名的用户。 --DROP USER HOST_A_user CREATE USER HOST_A_user FOR LOGIN HOST_A_login; GO --使证书与该用户关联。 --DROP CERTIFICATE HOST_A_cert CREATE CERTIFICATE HOST_A_cert AUTHORIZATION HOST_A_user FROM FILE = 'c:\backup\HOST_A_cert.cer' GO --授予对远程镜像端点的登陆名的 CONNECT 权限。 GRANT CONNECT ON ENDPOINT::Endpoint_Mirroring TO [HOST_A_login]; GO --在 HOST_B 上为 HOST_C 建立一个登陆名。 USE master; --DROP LOGIN HOST_C_login CREATE LOGIN HOST_C_login WITH PASSWORD = 'P@ssw0rd0'; GO --建立一个使用该登陆名的用户。 --DROP USER HOST_C_user CREATE USER HOST_C_user FOR LOGIN HOST_C_login; GO --使证书与该用户关联。 --DROP CERTIFICATE HOST_C_cert CREATE CERTIFICATE HOST_C_cert AUTHORIZATION HOST_C_user FROM FILE = 'c:\backup\HOST_C_cert.cer' GO --授予对远程镜像端点的登陆名的 CONNECT 权限。 GRANT CONNECT ON ENDPOINT::Endpoint_Mirroring TO [HOST_C_login]; GO --在 HOST_B 上为 HOST_B 建立一个登陆名。 USE master; --DROP LOGIN HOST_B_login CREATE LOGIN HOST_B_login WITH PASSWORD = 'P@ssw0rd0'; GO --建立一个使用该登陆名的用户。 --DROP USER HOST_B_user CREATE USER HOST_B_user FOR CERTIFICATE HOST_B_cert; GO --授予对远程镜像端点的登陆名的 CONNECT 权限。 GRANT CONNECT ON ENDPOINT::Endpoint_Mirroring TO [HOST_B_login]; GO --在 HOST_B 的镜像服务器实例上,将 HOST_A 上的服务器实例设置为伙伴(使其成为初始主体服务器实例)。 ALTER DATABASE crm SET PARTNER = 'TCP://192.168.1.203:5022'; GO /**************************** 见证服务器执行 *****************************/ --ALTER DATABASE MirrorDB SET PARTNER OFF USE master; --DROP MASTER KEY CREATE MASTER KEY ENCRYPTION BY PASSWORD = 'P@ssw0rd0'; GO --为此服务器实例制做一个证书。 --DROP CERTIFICATE HOST_C_cert CREATE CERTIFICATE HOST_C_cert WITH SUBJECT = 'HOST_C certificate',START_DATE = '01/01/2009'; GO --使用该证书为服务器实例建立一个镜像端点。 --DROP ENDPOINT Endpoint_Mirroring 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 --备份 HOST_C 证书,并将其复制到其余系统,即 HOST_B\HOST_A。 BACKUP CERTIFICATE HOST_C_cert TO FILE = 'c:\backup\HOST_C_cert.cer'; GO --为入站链接配置 Host_C --在 HOST_C 上为 HOST_B 建立一个登陆名。 USE master; --DROP LOGIN HOST_B_login CREATE LOGIN HOST_B_login WITH PASSWORD = 'P@ssw0rd0'; GO --建立一个使用该登陆名的用户。 --DROP USER HOST_B_user CREATE USER HOST_B_user FOR LOGIN HOST_B_login; GO --使证书与该用户关联。 --DROP CERTIFICATE HOST_B_cert CREATE CERTIFICATE HOST_B_cert AUTHORIZATION HOST_B_user FROM FILE = 'c:\backup\HOST_B_cert.cer' GO --授予对远程镜像端点的登陆名的 CONNECT 权限。 GRANT CONNECT ON ENDPOINT::Endpoint_Mirroring TO [HOST_B_login]; GO --在 HOST_C 上为 HOST_A 建立一个登陆名。 USE master; --DROP LOGIN HOST_A_login CREATE LOGIN HOST_A_login WITH PASSWORD = 'P@ssw0rd0'; GO --建立一个使用该登陆名的用户。 --DROP USER HOST_A_user CREATE USER HOST_A_user FOR LOGIN HOST_A_login; GO --使证书与该用户关联。 --DROP CERTIFICATE HOST_A_cert CREATE CERTIFICATE HOST_A_cert AUTHORIZATION HOST_A_user FROM FILE = 'c:\backup\HOST_A_cert.cer' GO --授予对远程镜像端点的登陆名的 CONNECT 权限。 GRANT CONNECT ON ENDPOINT::Endpoint_Mirroring TO [HOST_A_login]; GO --在 HOST_C 上为 HOST_C 建立一个登陆名。 USE master; --DROP LOGIN HOST_C_login CREATE LOGIN HOST_C_login WITH PASSWORD = 'P@ssw0rd0'; GO --建立一个使用该登陆名的用户。 --DROP USER HOST_C_user CREATE USER HOST_C_user FOR CERTIFICATE HOST_C_cert; GO 可能有朋友们会比较有疑惑,你一下搞两个数据库出来,他们的ip地址都不同,到时候数据库切换过去了,个人数据库的链接字符串可如何是好?难道还得在代码中去控制是链接哪一个数据库吗? 其实这个问题是这样的,使用ADO.NET或者SQL Native Client可以自动链接到故障转移后的伙伴,链接字符串以下所示: ConnectionString="DataSource= A;Failover Partner=B;Initial Catalog=AdventureWorks;Integrated Security=true;" DataSource= A;这个就是咱们经常使用的主数据库的ip地址,Failover Partner=B;这个填写的就是镜像数据库的ip地址,一旦出现了链接错误,ado.net会在超时之后自动去链接镜像数据库。 2.高级别保护模式 在昨天晚上加班作实施的时候,才发现个人设计已经被修改了,因为之前的项目有java写的也有c#写的,全自动的故障转移不可以实现。换句话说,因为老项目中的历史遗留问题,以及特殊模块的耦合性太高,没法解耦,只能在高级别保护模式或高性能模式中选择一种了。那么这二者有什么区别呢? 简单一点来讲,区别就在与事务安全模式上跟应用场景上。 高级别保护模式采用的是同步镜像, SAFETY FULL。应用场景:一般在局域网中或对数据要求比较高的场景中。 高性能保护模式采用的是异步镜像, SAFETY OFF。应用场景:一般在广域网或对数据要求不过高,丢失几条数据是容许的,可是必须保证它不中断服务。 在微软的SQLServer2005的课程上是这么说的。若是是高级别保护模式的话,主、从数据库只要有一台不能正常保证服务,数据库就不可以对外进行服务了,我在开始的时候就没有打算采用这种模式,由于部门经理说了,丢失一两条数据是能够接受的,何况咱们公司是作运营的,按照起先微软的课程的理论,高级别保护模式是不太适合咱们公司的应用场景的,万一有一台数据库出问题了,整个服务就被中断,这是不能让人接受的。再说了,公司对数据要求不太苛刻,两台服务器都有内网线链接,因为内网传输速度很是的快,即便采用高性能模式,通常来讲也是不会丢失数据的。因而我打算采用高性能模式来作数据库的镜像。因为公司服务器没有域环境,因此我就采用了证书验证来作SQLServer镜像。 意外收获: 两台服务器所有都安装了SQLServer2008,在设置事务安全模式的时候,才发现SQLServer2008不支持异步模式。提示大概以下:此SQLServer版本不支持修改事务安全模式,alter database失败。我当时汗都出来了,忙活了一夜,到最后竟然是这个结果。 因为是服务器维护时间,我大胆的把镜像服务器中止了,结果却让我大吃一惊,主数据库依旧能够正常工做,正常对外提供服务。也就是说,起先微软的课程讲的知识是错误的,两台数据库作镜像,不论是哪台数据库出了问题,另外的一台数据库均可以保证正常对外提供服务。因而我反复试验反复切换了一下,结果依然是这样。 因为高级别保护模式与高性能模式代码差不太多,只是在事务安全模式的设置上有些小区别,前面已经提到,这里就再也不多解释了。实施的代码以下: USE master; CREATE MASTER KEY ENCRYPTION BY PASSWORD = 'password'; CREATE CERTIFICATE HOST_A_cert WITH SUBJECT = 'HOST_A certificate' , START_DATE = '01/01/2012',EXPIRY_DATE ='01/01/2020'; ; 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 ); BACKUP CERTIFICATE HOST_A_cert TO FILE = 'c:\backup\HOST_A_cert.cer'; CREATE LOGIN HOST_B_login WITH PASSWORD = 'password'; CREATE USER HOST_B_user FOR LOGIN HOST_B_login; CREATE CERTIFICATE HOST_B_cert AUTHORIZATION HOST_B_user FROM FILE = 'c:\backup\HOST_B_cert.cer'; GRANT CONNECT ON ENDPOINT::Endpoint_Mirroring TO [HOST_B_login]; ALTER DATABASE crm SET PARTNER = 'TCP://10.10.10.8:5022'; USE master; CREATE MASTER KEY ENCRYPTION BY PASSWORD = 'password'; CREATE CERTIFICATE HOST_B_cert WITH SUBJECT = 'HOST_B certificate', START_DATE = '01/01/2012',EXPIRY_DATE ='01/01/2020'; ; 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 ); BACKUP CERTIFICATE HOST_B_cert TO FILE = 'c:\backup\HOST_B_cert.cer'; CREATE LOGIN HOST_A_login WITH PASSWORD = 'password'; CREATE USER HOST_A_user FOR LOGIN HOST_A_login; CREATE CERTIFICATE HOST_A_cert AUTHORIZATION HOST_A_user FROM FILE = 'c:\backup\HOST_A_cert.cer'; GRANT CONNECT ON ENDPOINT::Endpoint_Mirroring TO [HOST_A_login]; ALTER DATABASE crm SET PARTNER = 'TCP://10.10.10.6:5022'; 可能有朋友会比较奇怪,你这里也没有使用ALTER DATABASE crm SET SAFETY FULL; 按理应该是高性能模式才对呀? 其实这个问题是这样的,个人这个SQLServer2008默认已是将事务安全模式设置为full了,即便是手动设置也同样,而且我实施的时候SQLServer2008不支持将事务安全模式设置为OFF。 OK,一切都设置好了,那么就能够模拟服务器真的down机时候的操做了,后续的工做我也把代码作了总结,具体代码以下: --主备互换 --主机执行: ALTER DATABASE crm SET PARTNER FAILOVER --主服务器Down掉,备机紧急启动而且开始服务 ALTER DATABASE crm SET PARTNER FORCE_SERVICE_ALLOW_DATA_LOSS 原来的主服务器恢复,能够继续工做,须要从新设定镜像 --备机执行: USE master ALTER DATABASE crm SET PARTNER RESUME --恢复镜像 ALTER DATABASE crm SET PARTNER FAILOVER; --切换主备 3.监视数据库镜像 SQLServer提供了一些视图,能够供查询镜像的各类状态,到时候能够根据这个作一个监视,一旦发生故障转移群集,发邮件给系统管理员,好让系统管理员及时的知道数据库服务器发生了什么问题,即便的作故障分析、排查。有关这方面资料,MSDN上已经提供太多资料了。感兴趣的朋友能够去查这方面的资料。 在文章的最后提出一个有争议的问题:SQLServer(2008)高级别保护模式,只要有一台数据库可以保证正常运行,就能够正常对外提供服务。个人实验结果是这样的,这的确跟以往的理论知识有些出入。 还等什么,赶快搭环境动手实验一下吧,体验一下SQLServer镜像带来的快感。但愿有兴趣的朋友们一块儿学习探讨。