轉載自: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鏡像帶來的快感。但願有興趣的朋友們一塊兒學習探討。