複製預存程序執行應用於事務複製中,當在發行伺服器上執行配置的預存程序時,預存程序導致的資料變更不會做為多步驟事務發送到訂閱伺服器,而僅僅是把執行預存程序的命令發送到訂閱伺服器。
比如,如果你為一個100萬條記錄的表增加了一個欄位,並且初始化為一個值,如果不使用複製預存程序執行的話,那麼這個操作就會形成100萬個更新操作發送到訂閱伺服器,訂閱伺服器將將進行100萬次更新,這個操作通常會花費很長時間,並導致後續的資料變更也無法得到及時的同步。
如果使用複製預存程序執行的話,你可以建立一個預存程序來實現這個更新,並且把這個預存程序添加到事務複製中,然後當你在發行伺服器上執行完成這個預存程序後,這個執行操作會衩發送到訂閱伺服器,訂閱伺服器將執行同樣的調用預存程序的操作來完成這100萬記錄的更新。由於在發布和散發者之間不存在大量的資料傳遞,更新操作也不是100萬個更新,所以這個操作會很快完成,因此你的同步延遲也會非常小。
複製預存程序的關鍵是發布項目屬性中,為預存程序設定項目屬性時,將“複製”項設定為“預存程序執行”,或者是“SP 的序列化事務中執行”,
(如果你是用T-SQL來建立發布,則是將 sp_addarticle 預存程序的 @type 參數設定為“proc exec”,或“serializable proc exec”)
其中,“SP 的序列化事務中執行”是推薦的行為,要求你的預存程序是在序列化事務中,也就是SET TRANSACTION ISOLATION LEVEL SERIALIZABLE。至於原因和詳細的資料,可能參考線上說明:
http://msdn.microsoft.com/zh-cn/library/ms152754(SQL.90).aspx
值得注意的是,由於訂閱伺服器上的預存程序是可以修改的,所以利用這個,你還可能實現更多的與大批量資料相關的操作。例如,你可能有一些大表,這些表被同步到報表伺服器上,在你的發行伺服器上,你只關心最新的資料(可能是最近2年),而在報表伺服器上,你需要所有的資料。所以,在發行伺服器上,你可能有一個定期刪除曆史資料的Job,而在報表伺服器上,則不能刪除,你可能會考慮通過配置篩選來做到發布上的刪除不同步到訂閱,但如果某天不小心重新初始化了一次,則資料就丟失了。而利用複製預存程序執行的話,你可以在發行伺服器上定義預存程序的內容為刪除,在訂閱伺服器上定義預存程序為刪除並且OUTPUT 到曆史表,這樣發布和訂閱的表是一樣的,不擔心重新初台化導致資料丟失。唯一要注意的是,你在發行伺服器上修改預存程序的話,這個修改會同步到訂閱伺服器,當然,這個問題也容易解決,你可以在預存程序裡面判斷伺服器名字來完成不同的操作,這樣就萬無一失了。