1. 程式人生 > >SQL Server 通過備份檔案初始化複製

SQL Server 通過備份檔案初始化複製

一.本文所涉及的內容(Contents)

二.背景(Contexts)

  MySQL在對有歷史資料的資料庫進行搭建複製(Master/Slave)的時候,可以通過在Master伺服器備份歷史資料,利用這個備份檔案在Slave進行還原;這樣做的好處是可以更加快速的搭建好環境,因為可以對備份檔案進行壓縮、分包,並且可以使用FTP等工具保證傳輸過程的安全與快捷;詳情可參考:Windows下搭建MySQL Master Slave

  當SQL Server遇到同樣需要對歷史資料庫搭建複製,通常的做法是在本地釋出快照,再由訂閱傳輸資料,那SQL Server應該如何實現備份歷史資料搭建複製(釋出/訂閱)呢?下圖是備份檔案初始化訂閱的基本邏輯結構圖:

clip_image002

(Figure0:備份檔案初始化訂閱邏輯結構圖)

三.搭建過程(Process)

(一) 環境資訊

系統環境:Windows Server 2008 + SQL Server 2008

釋出伺服器:192.168.1.105,伺服器名稱:QuZhoushiwei105

分發伺服器:與釋出伺服器同一臺機器

訂閱伺服器:192.168.1.106,伺服器名稱:QuZhoushiwei106

釋出資料庫:Barfoo.TestPublish

訂閱資料庫:Barfoo.TestSubscribe

資料庫帳號:ReplicationUser/ ReplicationPassword

說明:釋出伺服器與訂閱伺服器是在同一內網的機器,如果你的環境是跨網段(跨機房)的請參考:

SQL Server 跨網段(跨機房)部署

(二) 搭建步驟

1) 在釋出伺服器上以QuZhoushiwei105伺服器名稱登陸釋出伺服器,如果你以localhost或者IP形式登陸伺服器,在建立釋出的時候會出現下圖Figure1的錯誤資訊;

clip_image004

(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'廣州')

clip_image005

(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) 在釋出伺服器上建立一個釋出,具體步驟如下圖所示:

clip_image006

(Figure3:新建釋出)

clip_image007

(Figure4:選擇資料Barfoo.TestPublish)

clip_image008

(Figure5:選擇事務釋出)

clip_image009

(Figure6:選擇需要釋出的欄位)

clip_image010

(Figure7:不勾選)

clip_image011

(Figure8:設定快照代理)

clip_image012

(Figure9:設定代理安全性)

clip_image013

(Figure10:設定日誌讀取器代理)

clip_image014

(Figure11:設定帳號密碼)

clip_image015

(Figure12:建立釋出)

clip_image016

(Figure13:釋出名稱)

clip_image017

(Figure14:建立成功)

clip_image018

(Figure15:建立的釋出)

4) 設定釋出屬性中的訂閱選項,把允許從備份檔案初始化的預設值false設定為true;也可以使用下面的SQL指令碼進行修改;

clip_image019

(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指令碼執行成功,資料庫會返回下面的提示資訊:

clip_image021

(Figure17:建立訂閱返回資訊)

注意:如果備份檔案之後相隔太長時間,執行上面的指令碼有可能會出現下面的錯誤資訊,如果遇到這個問題,可以參考下面【疑問】的內容:

訊息21397,級別16,狀態1,過程sp_MSaddautonosyncsubscription,第271 行

對從指定備份建立的非同步訂閱進行同步時需要一些事務,但這些事務在分發伺服器上不可用。請使用更新的日誌以及差異或完整資料庫備份再試此操作。

9) 檢查新新增的訂閱屬性中的安全性->訂閱伺服器連線,確認正確的帳號和密碼,預設是使用代理帳號;

clip_image022

(Figure18:訂閱伺服器屬性)

clip_image024

(Figure19:設定安全性)

clip_image026

(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) 檢查釋出伺服器和訂閱伺服器的訂閱狀態;

clip_image027

(Figure21:啟動複製監視器)

clip_image029

(Figure22:訂閱狀態)

clip_image030

(Figure23:訂閱伺服器的本地訂閱)

11) 檢視訂閱伺服器QuZhoushiwei106的資料庫Barfoo.TestSubscribe的UserInfo表的資料;

clip_image031

(Figure24:UserInfo表資料)

12) 使用下面的SQL指令碼在釋出伺服器上UserInfo表插入新資料,測試複製,分別檢視釋出伺服器與訂閱伺服器的資料;

--測試訂閱資料
INSERT [dbo].[UserInfo] ([names],[address]) VALUES (N'viajar', N'北京')

clip_image032

(Figure25:釋出伺服器上UserInfo表資料)

clip_image033

(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;

clip_image034

(Figure27:資料庫只讀)

C. 最後一種方式最常使用,是建立好釋出之後馬上關掉distributor cleanup這個JOB,可參考:Implementing NoSync Initializations (and variations) on SQL Server 2005/8(CareySon),關掉這個JOB,建立訂閱之後資料會同步到訂閱伺服器上,但是不會對訂閱執行dbo.sp_MSdistribution_cleanup,可以使用CHECKPOINT 1進行測試;

clip_image035

(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

clip_image037

(Figure29:訂閱配置資訊)

六.參考文獻(References)