??? 在服務器A數據庫TEST新建了一個本地發布(Local Publications)RPL_GES_MIS_TEST,在服務器B數據庫RPL_TEST上創建了一個本地訂閱(Local Subscriptions),它訂閱了了這個發布RPL_GES_MIS_TEST.如下截圖所示,本地發布只有DB_OBJECTS 、Location兩個表
假設現在有一個需求,我們需要同步一個視圖V_DB_OBJECTS(當然實際情況應該比這個復雜,有可能視圖是多個表關聯,測試場景我們先簡化一下),視圖代碼如下
CREATE?VIEW V_DB_OBJECTS
AS
?SELECT * FROM DB_OBJECTS WHERE type !='S';
我們右鍵單擊RPL_GES_MIS_TEST的屬性,在Articles里面添加了該視圖
此時我們使用sp_helpsubscription查看訂閱的特定的發布、項目、訂閱服務器或訂閱集關聯的訂閱信息。就會發現視圖V_DB_OJBECTS的subscription status為1,表示訂閱服務器正在請求數據,但尚未同步。
此時你右鍵單擊對應的本地發布RPL_GES_MIS_TEST,選擇“View Snapshopt Agent Status",如下所示,你會看到它提示快照生成了2個項目,意味著其實這個視圖不在快照里面。
此時,你點擊開始,重新生成快照,你會發現下面信息。快照重新初始化了3個項目。
那么我們有沒有辦法,在發布訂閱里面,只同步一個新的視圖,而不用初始化整個快照嗎? 答案是有,其實方法很簡單,具體可以參考我這篇文章SQL SERVER Transactional Replication中添加新表如何不初始化整個快照 。此處不做展開分析
CREATE?VIEW V_DB_OBJECTS_2
AS
?SELECT * FROM DB_OBJECTS WHERE type !='S'
?
?
?
USE TEST;
GO
?
EXEC sp_changepublication
@publication = 'RPL_GES_MIS_TEST',
@property = 'allow_anonymous' ,
@value = 'false'
GO
EXEC sp_changepublication
@publication = 'RPL_GES_MIS_TEST',
@property = 'immediate_sync' ,
@value = 'false'
GO?
執行上面腳本后,我們在發布里面的項目(Articles)里面添加視圖V_DB_OBJECTS_2,然后我們在View Snapshot Agent Status窗口,單擊“Start"按鈕,你會發現快照只生成了這個視圖。如下所示
另外,可能有同學有疑問,如果我的視圖已經通過Replication同步了,那么我修改視圖有沒有影響?會不會也同步過去呢? 如下所示,修改V_DB_OBJECTS_2
你會發現修改過后的視圖很快就同步到訂閱服務的數據庫上,但是要注意,如果選項”Replicate schema changes"為False,那么此時對視圖的修改是不會同步過去
另外需要注意:對視圖的修改僅僅限制在視圖的引用對象也在復制(Replication)當中,如果引用了一個不在復制(Replication)的項目,那么此時就會有問題了。其實不光是修改已經同步的視圖,其實同步一張新的視圖,如果視圖引用的項目(對象)不在發布訂閱(Replication)當中也會有問題,它會報如下錯誤:
Unable to replicate a view or function because the referenced objects or columns are not present on the Subscriber.
還有一種情況就是視圖所引用的對象都在發布訂閱當中,但是視圖跨越了多個數據庫,那么是否也有問題呢?
如下所示,視圖引用了TEST數據庫的表DB_OBJECTS和TTT數據庫的表mmFrameModel, 而且TTT數據庫的表mmFrameModel也同步到了訂閱數據庫RPL_DB_TEST當中,但是此時同步依然會有問題
CREATE?VIEW V_TEST2
AS
?SELECT name? AS NAME? FROM DB_OBJECTS
?UNION?ALL
?SELECT Machine_Model AS NAME FROM TTT.dbO.mmFrameModel;
有一個替換方案就是不同步視圖,而是在同步了視圖引用的對象后,在訂閱的數據庫上也創建同樣邏輯的視圖。只是這個替換方案有點麻煩的是,在修改了發布數據庫上的視圖后,一定要記得也同時手動修改訂閱數據庫的視圖