共用方式為


在事務性複製中發佈存儲過程的執行

如果您有一或多個在發行者執行並影響已發行資料表的預存程式,請考慮將這些預存程式納入您的發行項作為預存程式執行項目。 初始化訂閱時,程式的定義會復寫到訂閱者;當程式在發行者端執行時,複寫會在訂閱者端執行對應的程式。 這可為執行大型批次作業的情況提供顯著的效能,因為只會復寫程序執行,而略過複寫每個數據列個別變更的需求。 例如,假設您在出版資料庫中建立下列預存程式:

CREATE PROC give_raise AS  
UPDATE EMPLOYEES SET salary = salary * 1.10  

此程式為貴公司的 10,000 名員工提供 10% 的加薪。 當您在發行者端執行這個預存程式時,它會更新每位員工的薪資。 若未復寫預存程序執行,更新會以大型多步驟交易的形式傳送給訂閱者:

BEGIN TRAN  
UPDATE EMPLOYEES SET salary = salary * 1.10 WHERE PK = 'emp 1'  
UPDATE EMPLOYEES SET salary = salary * 1.10 WHERE PK = 'emp 2'  

此過程會重複執行 10,000 次更新。

復寫預存程式執行時,複寫只會傳送命令來執行訂閱者端的預存程式,而不是將所有更新寫入散發資料庫,然後透過網路傳送至訂閱者:

EXEC give_raise  

這很重要

預存程式復寫不適用於所有應用程式。 如果橫向篩選文章,以致出版者端的行集不同於訂戶端,則在兩者端執行相同的預存程序會返回不同的結果。 同理,如果更新是以另一個非重複同步資料表的子查詢語句為基礎,則在發行者和訂閱者端執行相同的預存程式,將會返回不同的結果。

發佈預存程序的執行

修改訂閱者端的程序

根據預設,發行者端的預存程式定義會傳播至每個訂閱者。 不過,您也可以修改訂閱者端的預存程式。 如果您想要在「發行者」和「訂閱者」端執行不同的邏輯,這會很有用。 例如,請考慮 sp_big_delete,這是發行者端有兩個函式的預存程式:它會從復寫數據表中刪除 1,000,000 個數據列 ,big_table1 並更新非重複的數據表 big_table2。 若要減少對網路資源的需求,您應該藉由發佈 sp_big_delete,將 1 百萬個數據列刪除傳播為預存程式。 在訂閱者端,您可以修改 sp_big_delete 只刪除 1 百萬個數據列,而不會執行後續 big_table2更新。

備註

根據預設,在發行者端使用 ALTER PROCEDURE 所做的任何變更會傳播至訂閱者。 若要避免這種情況,請在執行 ALTER PROCEDURE 之前停用架構變更的傳播。 如需架構變更的相關信息,請參閱 在發行集資料庫上進行架構變更

預存程式執行發行項的類型

有兩種不同的方式可以發行預存程式的執行:可串行化的程式執行發行項和程式執行發行項。

  • zh-TW: 建議使用可串行化選項,因為只有在程序是在可串行化交易的情境中執行時,才會重複執行程序。 如果預存程式是從可串行化交易外部執行,則發行數據表中的數據變更會復寫為一系列的 DML 語句。 此行為有助於讓訂閱者端的數據與發行者端的數據保持一致。 這對於批次作業特別有用,例如大型清除作業。

  • 使用程式執行選項時,不論預存程式中的個別語句是否成功,都可以將執行複寫到所有訂閱者。 此外,由於預存程式對數據所做的變更可能會在多個交易內發生,因此訂閱者端的數據可能與發行者端的數據不一致。 若要解決這些問題,訂閱者必須是只讀的,而且您使用的隔離等級必須大於「未認可的讀取」。 如果您使用未提交讀取,已發佈數據表中的數據變更會以一系列的 DML 語句進行複製。

下列範例說明為何建議您將程序復寫設定為可串行化的程序發行項。

BEGIN TRANSACTION T1  
SELECT @var = max(col1) FROM tableA  
UPDATE tableA SET col2 = <value>   
   WHERE col1 = @var   
  
BEGIN TRANSACTION T2  
INSERT tableA VALUES <values>  
COMMIT TRANSACTION T2  

在上述範例中,假設交易 T1 中的 SELECT 發生在交易 T2 中的 INSERT 之前。

如果程式未在可串行化交易內執行(隔離等級設定為SERIALIZABLE),交易 T2 將允許在 T1 中的 SELECT 語句範圍內插入新的數據列,且會在 T1 之前認可。 這也表示它會在 T1 之前套用在訂閱者端。 在訂閱者端套用 T1 時,SELECT 可能會傳回與發行者不同的值,而且可能會產生與 UPDATE 不同的結果。

如果程式是在可串行化的交易內執行,則不允許交易 T2 插入 T2 中 SELECT 語句所涵蓋的範圍。 在 T1 認可確保訂閱者端的相同結果之前,將會封鎖它。

當您在可串行化交易中執行程序時,鎖定時間會延長,並可能導致並行性降低。

XACT_ABORT設定

複寫預存程式執行時,執行預存程式的會話設定應該指定XACT_ABORT ON。 如果XACT_ABORT設定為 OFF,並在發行者端執行程式期間發生錯誤,則訂閱者端會發生相同的錯誤,導致散發代理程序失敗。 指定 XACT_ABORT ON 可確保在發行者端執行期間發生的任何錯誤都會讓整個執行復原,以避免散發代理程式失敗。 如需設定XACT_ABORT的詳細資訊,請參閱 SET XACT_ABORT (Transact-SQL)

如果您需要設定 XACT_ABORT OFF,請指定散發代理程式的 -SkipErrors 參數。 這可讓代理程式繼續在訂閱者端套用變更,即使發生錯誤也一樣。

另請參閱

交易複寫的文章選項