SQL Server 通過備份檔案初始化複製
一.本文所涉及的內容(Contents)
二.背景(Contexts)
MySQL在對有歷史資料的資料庫進行搭建複製(Master/Slave)的時候,可以通過在Master伺服器備份歷史資料,利用這個備份檔案在Slave進行還原;這樣做的好處是可以更加快速的搭建好環境,因為可以對備份檔案進行壓縮、分包,並且可以使用FTP等工具保證傳輸過程的安全與快捷;詳情可參考:Windows下搭建MySQL Master Slave
當SQL Server遇到同樣需要對歷史資料庫搭建複製,通常的做法是在本地釋出快照,再由訂閱傳輸資料,那SQL Server應該如何實現備份歷史資料搭建複製(釋出/訂閱)呢?下圖是備份檔案初始化訂閱的基本邏輯結構圖:
(Figure0:備份檔案初始化訂閱邏輯結構圖)
三.搭建過程(Process)
(一) 環境資訊
系統環境:Windows Server 2008 + SQL Server 2008
釋出伺服器:192.168.1.105,伺服器名稱:QuZhoushiwei105
分發伺服器:與釋出伺服器同一臺機器
訂閱伺服器:192.168.1.106,伺服器名稱:QuZhoushiwei106
釋出資料庫:Barfoo.TestPublish
訂閱資料庫:Barfoo.TestSubscribe
資料庫帳號:ReplicationUser/ ReplicationPassword
說明:釋出伺服器與訂閱伺服器是在同一內網的機器,如果你的環境是跨網段(跨機房)的請參考:
(二) 搭建步驟
1) 在釋出伺服器上以QuZhoushiwei105伺服器名稱登陸釋出伺服器,如果你以localhost或者IP形式登陸伺服器,在建立釋出的時候會出現下圖Figure1的錯誤資訊;
(Figure1:錯誤資訊)
登陸伺服器之後使用下面的SQL指令碼建立一個測試資料庫:Barfoo.TestPublish,建立一個測試表:UserInfo,並插入一條資料,用於模擬歷史資料;
--建立測試資料庫 USE MASTER GO CREATE DATABASE [Barfoo.TestPublish] GO --建立測試表 USE [Barfoo.TestPublish] GO CREATE TABLE [dbo].[UserInfo]( [Id] [int] IDENTITY(1,1) NOT FOR REPLICATION NOT NULL, [names] [nvarchar](50) NULL, [address] [nvarchar](50) NULL, CONSTRAINT [PK_UserInfo] PRIMARY KEY CLUSTERED ( [Id] ASC ) ON [PRIMARY] ) ON [PRIMARY] GO --插入測試資料 INSERT [dbo].[UserInfo] ([names],[address]) VALUES (N'gaizai', N'廣州')
(Figure2:UserInfo表記錄)
2) 在釋出資料庫和訂閱伺服器上分別執行下面的SQL指令碼建立帳號和密碼(ReplicationUser/ ReplicationPassword);
--釋出伺服器建立帳號密碼 USE [master] GO CREATE LOGIN [ReplicationUser] WITH PASSWORD=N'ReplicationPassword', DEFAULT_DATABASE=[master], CHECK_EXPIRATION=OFF, CHECK_POLICY=OFF GO EXEC master..sp_addsrvrolemember @loginame = N'ReplicationUser', @rolename = N'sysadmin' GO USE [Barfoo.TestPublish] GO CREATE USER [ReplicationUser] FOR LOGIN [ReplicationUser] GO USE [Barfoo.TestPublish] GO ALTER USER [ReplicationUser] WITH DEFAULT_SCHEMA=[dbo] GO --訂閱伺服器建立帳號密碼 USE [master] GO CREATE LOGIN [ReplicationUser] WITH PASSWORD=N'ReplicationPassword', DEFAULT_DATABASE=[master], CHECK_EXPIRATION=OFF, CHECK_POLICY=OFF GO EXEC master..sp_addsrvrolemember @loginame = N'ReplicationUser', @rolename = N'sysadmin' GO
3) 在釋出伺服器上建立一個釋出,具體步驟如下圖所示:
(Figure3:新建釋出)
(Figure4:選擇資料Barfoo.TestPublish)
(Figure5:選擇事務釋出)
(Figure6:選擇需要釋出的欄位)
(Figure7:不勾選)
(Figure8:設定快照代理)
(Figure9:設定代理安全性)
(Figure10:設定日誌讀取器代理)
(Figure11:設定帳號密碼)
(Figure12:建立釋出)
(Figure13:釋出名稱)
(Figure14:建立成功)
(Figure15:建立的釋出)
4) 設定釋出屬性中的訂閱選項,把允許從備份檔案初始化的預設值false設定為true;也可以使用下面的SQL指令碼進行修改;
(Figure16:Allow initialization from backup files)
--修改發表允許從備份中初始化 USE [Barfoo.TestPublish] GO DECLARE @publication AS sysname SET @publication = N'testpub' EXEC sp_changepublication @publication = @publication, @property = N'allow_initialize_from_backup', @value = true GO
5) 使用下面的SQL指令碼備份資料庫Barfoo.TestPublish,保留備份檔案,在後面建立訂閱的時候需要用到;
--備份資料 BACKUP DATABASE [Barfoo.TestPublish] TO DISK = N'G:\DBBackup\Barfoo.TestPublish_20130822.bak' WITH NOFORMAT, NOINIT, NAME = N'Barfoo.TestPublish-完整資料庫備份', SKIP, NOREWIND, NOUNLOAD, STATS = 10 GO
6) 在訂閱伺服器:192.168.1.106上使用下面的SQL指令碼還原剛剛的備份檔案;
--還原資料庫 RESTORE DATABASE [Barfoo.TestSubscribe] FROM DISK = N'G:\DBBackup\Barfoo.TestPublish_20130822.bak' WITH FILE = 1, MOVE N'Barfoo.TestPublish' TO N'G:\DataBase\Barfoo.TestSubscribe.mdf', MOVE N'Barfoo.TestPublish_log' TO N'G:\DataBase\Barfoo.TestSubscribe_log.ldf', NOUNLOAD, REPLACE, STATS = 10 GO
7) 在訂閱伺服器行修改帳號ReplicationUser,SQL指令碼如下:
--修改帳號ReplicationUser USE [Barfoo.TestSubscribe] GO ALTER USER [ReplicationUser] WITH DEFAULT_SCHEMA=[dbo] GO
8) 在釋出伺服器上執行sp_addsubscription儲存過程新增訂閱,SQL指令碼如下:
--在釋出伺服器建立訂閱 EXEC sp_addsubscription @publication = N'testpub', @subscriber ='QuZhoushiwei106', @destination_db = N'Barfoo.TestSubscribe', @subscription_type = N'Push', @sync_type = N'initialize with backup', @backupdevicetype='disk', @backupdevicename='G:\DBBackup\Barfoo.TestPublish_20130822.bak'
如果上面的SQL指令碼執行成功,資料庫會返回下面的提示資訊:
(Figure17:建立訂閱返回資訊)
注意:如果備份檔案之後相隔太長時間,執行上面的指令碼有可能會出現下面的錯誤資訊,如果遇到這個問題,可以參考下面【疑問】的內容:
訊息21397,級別16,狀態1,過程sp_MSaddautonosyncsubscription,第271 行
對從指定備份建立的非同步訂閱進行同步時需要一些事務,但這些事務在分發伺服器上不可用。請使用更新的日誌以及差異或完整資料庫備份再試此操作。
9) 檢查新新增的訂閱屬性中的安全性->訂閱伺服器連線,確認正確的帳號和密碼,預設是使用代理帳號;
(Figure18:訂閱伺服器屬性)
(Figure19:設定安全性)
(Figure20:設定登入名密碼)
也可以通過下面的SQL指令碼設定訂閱伺服器連線的帳號密碼:
--設定訂閱伺服器帳號密碼 EXEC sp_addpushsubscription_agent @publication = N'testpub', @subscriber = N'QUZHOUSHIWEI106', @subscriber_db = N'Barfoo.TestSubscribe', @subscriber_security_mode = 0, @subscriber_login = N'ReplicationUser', @subscriber_password = N'ReplicationPassword'
10) 檢查釋出伺服器和訂閱伺服器的訂閱狀態;
(Figure21:啟動複製監視器)
(Figure22:訂閱狀態)
(Figure23:訂閱伺服器的本地訂閱)
11) 檢視訂閱伺服器QuZhoushiwei106的資料庫Barfoo.TestSubscribe的UserInfo表的資料;
(Figure24:UserInfo表資料)
12) 使用下面的SQL指令碼在釋出伺服器上UserInfo表插入新資料,測試複製,分別檢視釋出伺服器與訂閱伺服器的資料;
--測試訂閱資料 INSERT [dbo].[UserInfo] ([names],[address]) VALUES (N'viajar', N'北京')
(Figure25:釋出伺服器上UserInfo表資料)
(Figure26:訂閱伺服器上UserInfo表資料)
四.注意事項(Attention)
1. 在SQL SERVER下實現釋出伺服器和訂閱伺服器的通訊正常(即可以互訪),開啟1433埠,在防火牆中設定入站規則;
2. 釋出伺服器與訂閱伺服器的SQL Server Agent代理帳號必須設定的一樣,否則不能互訪;
3. 後期新增新的表需要手動在訂閱伺服器建立表結構,主要先在釋出屬性的專案中勾選新表,再通過表的右鍵選單建立表結構指令碼。
五.疑問(Questions)
(一) 怎麼確保在釋出伺服器持續進資料的情況下,如何保證在拷貝歷史資料備份之後還能知道訂閱從哪個LSN開始讀取?
解答:如果備份檔案之後相隔太長時間,執行上面的指令碼有可能會出現下面的錯誤資訊:
訊息21397,級別16,狀態1,過程sp_MSaddautonosyncsubscription,第271 行
對從指定備份建立的非同步訂閱進行同步時需要一些事務,但這些事務在分發伺服器上不可用。請使用更新的日誌以及差異或完整資料庫備份再試此操作。
如果遇到這個問題,有3種解決辦法:
A. 按照上面的提示,對Barfoo.TestPublish資料庫做一個差異備份,再在Barfoo.TestSubscribe資料庫做差異還原,需要注意的是在使用sp_addsubscription的時候應該指定差異備份的檔案;
--差異備份資料庫 BACKUP DATABASE [Barfoo.TestPublish] TO DISK = N'G:\DBBackup\Barfoo.TestPublish_Diff_20130822.bak' WITH NOFORMAT, NOINIT, DIFFERENTIAL, NAME = N'Barfoo.TestPublish-差異資料庫備份', SKIP, NOREWIND, NOUNLOAD, STATS = 10 GO --完整還原資料庫 RESTORE DATABASE [Barfoo.TestSubscribe] FROM DISK = N'G:\DBBackup\Barfoo.TestPublish_20130822.bak' WITH FILE = 1, MOVE N'Barfoo.TestPublish' TO N'G:\DataBase\Barfoo.TestSubscribe.mdf', MOVE N'Barfoo.TestPublish_log' TO N'G:\DataBase\Barfoo.TestSubscribe_log.ldf', NOUNLOAD, REPLACE, NORECOVERY, STATS = 10 GO --差異還原資料庫 RESTORE DATABASE [Barfoo.TestSubscribe] FROM DISK = N'G:\DBBackup\Barfoo.TestPublish_Diff_20130822.bak' WITH FILE = 1, MOVE N'Barfoo.TestPublish' TO N'G:\DataBase\Barfoo.TestSubscribe.mdf', MOVE N'Barfoo.TestPublish_log' TO N'G:\DataBase\Barfoo.TestSubscribe_log.ldf', NOUNLOAD, STATS = 10 GO --在釋出伺服器建立訂閱 EXEC sp_addsubscription @publication = N'testpub', @subscriber ='QuZhoushiwei106', @destination_db = N'Barfoo.TestSubscribe', @subscription_type = N'Push', @sync_type = N'initialize with backup', @backupdevicetype='disk',
@backupdevicename='G:\DBBackup\Barfoo.TestPublish_Diff_20130822.bak'
B. 如果你的資料庫Barfoo.TestPublish可以接受短時間不寫入資料,可以在做完整備份之前就先設定資料庫為只讀狀態,在資料庫【屬性】-【選項】-【狀態】-【資料庫為只讀】設定為True;
(Figure27:資料庫只讀)
C. 最後一種方式最常使用,是建立好釋出之後馬上關掉distributor cleanup這個JOB,可參考:Implementing NoSync Initializations (and variations) on SQL Server 2005/8(CareySon),關掉這個JOB,建立訂閱之後資料會同步到訂閱伺服器上,但是不會對訂閱執行dbo.sp_MSdistribution_cleanup,可以使用CHECKPOINT 1進行測試;
(Figure28:分發清除)
(二) 如果是transactional的replication,建立完畢之後是會產生對應的三個Job,下面3個是複製作業中的Job,他們的作用分別是什麼呢?
A. QUZHOUSHIWEI105-Barfoo.TestPublish-12
B. QUZHOUSHIWEI105-Barfoo.TestPublish-testpub-12
C. QUZHOUSHIWEI105-Barfoo.TestPublish-testpub-QUZHOUSHIWEI106-22
QUZHOUSHIWEI105-Barfoo.TestPublish-12,這是REPL-LogReader類別的JOB,一個數據庫只會有一個日誌讀取器作業,命名的格式是:ServerName-DBName-Num;
QUZHOUSHIWEI105-Barfoo.TestPublish-testpub-12,這是REPL-Snapshot類別,的JOB,一個釋出(也叫做一條同步鏈)對應一個快照作業,命名的格式是:ServerName-DBName-PublishName-Num;
QUZHOUSHIWEI105-Barfoo.TestPublish-testpub-QUZHOUSHIWEI106-22,這是一個REPL-Distribution類別的JOB,一個訂閱對應一個分發作業,命名的格式是:ServerName-DBName-PublishName-ServerName-Num;
可以通過下面的SQL指令碼查詢訂閱JOB和訂閱屬性的相關資訊:
--返回訂閱資訊 SELECT * FROM msdb.dbo.sysjobs WHERE category_id=10 --返回訂閱屬性資訊 SELECT [description] ,[name] ,[allow_initialize_from_backup] ,[min_autonosync_lsn] FROM [Barfoo.TestPublish].[dbo].[syspublications] GO
(Figure29:訂閱配置資訊)