在伺服器A資料庫TEST新建了一個本地發佈(Local Publications)RPL_GES_MIS_TEST,在伺服器B資料庫RPL_TEST上創建了一個本地訂閱(Local Subscriptions),它訂閱了了這個發佈RPL_GES_MIS_TEST.如下截圖所示,本地發佈只有DB_OB...
在伺服器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;
有一個替換方案就是不同步視圖,而是在同步了視圖引用的對象後,在訂閱的資料庫上也創建同樣邏輯的視圖。只是這個替換方案有點麻煩的是,在修改了發佈資料庫上的視圖後,一定要記得也同時手動修改訂閱資料庫的視圖