事務複製中訂閱節點非活動( inactive)錯誤 在SQLServer的事務複製模型中,會出現“訂閱過期”的錯誤,相關訂閱分發代理Job的典型錯誤如下:"Agent SQLNYC01-Onvoices-PubInvoicesInvoices-SQLNYC01-1353 is retrying af ...
事務複製中訂閱節點非活動( inactive)錯誤
在SQLServer的事務複製模型中,會出現“訂閱過期”的錯誤,
相關訂閱分發代理Job的典型錯誤如下:"Agent SQLNYC01-Onvoices-PubInvoicesInvoices-SQLNYC01-1353 is retrying after an error. N retries attempted. See agent job history in the Jobs folder for more details."
Job的詳細錯誤如下: “Error in replication::subscription(s) have been marked inactive and must be reinitialized”這一類錯誤
意思是分發Job經過N次的重試失敗,詳細錯誤錶面訂閱伺服器被標記為非活動狀態,必須重新初始化。
該異常的原因在於訂閱節點長期無法被(發佈節點)訪問,超出分發數據的保留期限(預設是72小時),訂閱被標記為非活動狀態,
解決方案如下:
1,在確保訂閱節點可以正常被訪問的情況下,需要重新對發佈創建一個快照,重新用快照初始化訂閱來“激活”訂閱
2,在確保訂閱節點可以正常被訪問的情況下,通過修改系統表distribution..MSsubscriptions set status=2的訂閱狀態來激活訂閱,但是這種方式仍舊需要考慮數據的一致性問題
1:將事務複製設置為持續運行時,分發代理Job作業將重試多少次?
參考下,事務分發Job負責從distribution庫將日誌傳遞到訂閱節點,如果訂閱節點不可訪問,該Job將持續重試2147483647,這個數字是int類型的最大值 ,重試的間隔為1分鐘,也可以理解為該Job將無限期永久性持續重試。
代理作業的歷史日誌查詢
Select * from Distribution.dbo.MSdistribution_history where [Time] > dateadd(hh,-24,getdate()) and comments like '%is retrying after an error%' order by [Time] desc or Select t1.[Time] as 'Logged Time', UPPER(t2.name) as 'Disribution Agent Name', LTRIM(RTRIM((Replace(Substring(t1.comments, charindex('.',t1.comments), charindex('retries',t1.comments)-charindex('.',t1.comments)),'.','')))) as 'Total Retries Attempted', Substring(t1.comments, charindex('VM',t1.comments), 4) as 'Subscriber' from Distribution.dbo.MSdistribution_history t1 Inner Join Distribution.dbo.MSdistribution_agents t2 on t1.agent_id = t2.id where comments like '%retries attempted%' and [Time] > dateadd(hh,-24,getdate()) order by 4, t1.[Time] desc
2:分發代理會在無限制連續重試的情況下失敗(而停止)嗎?(例如:間歇性網路連接問題)
在這種情況下,分發代理將繼續重試2147483647次。然而,在通過了下麵的Transaction Retention設置之後,系統將做出反應並導致失敗。如下截圖(SSMS. Replication Properties打開)
這就是所謂的“分發的事務保留期”。預設是保留72小時,如果Job連續錯誤重試超過72小時,可能會出現以下故障:
"18854 One or more subscriptions have been marked inactive. Drop and re-create all subscriptions for this node that are failing with this error."
"The subscription(s) have been marked inactive and must be reinitialized. NoSync subscriptions will need to be dropped and recreated. (Source: MSSQLServer, Error number: 21074"
註意上面的72小時這個參數,過期的事務日誌數據是通過“Distribution clean up: distribution”這個Job清理的,該Job10分運行一次,通過修改But not more than輸入框的參數,可以影響“Distribution clean up: distribution”job中執行腳本的參數@max_distretention這個參數的賦值。但是奇葩的是,如果修改Job中的SQL中的@max_distretention參數,不會聯動修改上圖中But not more than輸入框的數據顯示。
這個參數本質上就是將distribution中超過72小時(時間可以自定義)的日誌刪除。
3:如何監控Replication系統中發生的導致複製中斷的錯誤?
分發數據distribution中記錄了事務複製過程中產生的錯誤日誌,設置SQL作業來監視、記錄和警告某些錯誤,並立即修複這些錯誤,以避免訂閱變得中斷。
最經典的錯誤如下
20598 - The row was not found at the Subscriber when applying the replicated command.
2627 - Violation of PRIMARY KEY constraint ‘PK_TBL’. Cannot insert duplicate key in object ‘dbo.TBL’.
利用如下SQL可以監控事務複製中發生的錯誤信息:
Use Distribution go Declare @RepErrorsNew int --check last 5 mins; sql job executes every 5 mins Select @RepErrorsNew = (select top 1 ID from Distribution.dbo.MSrepl_errors with (nolock) where error_text like '%The row was not found at the Subscriber when applying the replicated command.%' and [time] > dateadd(mi,-15,getdate()) order by [time] desc) If @RepErrorsNew IS NOT NULL and @RepErrorsNew > 0 Begin RAISERROR('Transactional Replication Error Alert - Row Not Found!', 16, 1) End Use Distribution go Declare @RepErrorsNew int --check last 5 mins; sql job executes every 5 mins Select @RepErrorsNew = (select top 1 ID from Distribution.dbo.MSrepl_errors with (nolock) where error_text like '%Violation of PRIMARY KEY constraint%' and [time] > dateadd(mi,-5,getdate()) order by [time] desc) If @RepErrorsNew IS NOT NULL and @RepErrorsNew > 0 Begin RAISERROR('Transactional Replication Error Alert - Violation of PRIMARY KEY constraint!', 16, 1) End
4:在事務性複製中還有其他保留期的設置嗎?
是的!它被稱為“發佈保存期”。要查找此設置,SSMS---複製---本地發佈,右鍵單擊發佈並選擇屬性。然後在常規選項卡中找到訂閱過期部分。下麵的截圖很好地解釋了這一點。
以下是微軟對這兩種複製保留期限的說明:
事務複製使用最大分發保留期(sp_adddistributiondb (Transact-SQL)的@ max_distributiontion參數)和發佈保留期(sp_addpublication (Transact-SQL)的@retention參數):
如果在最大分發保留期限(預設為72小時)內未同步訂閱,並且分發資料庫中存在未傳遞給訂閱伺服器的更改,則該訂閱將被運行在分發伺服器上的分發清理作業標記為未激活。必須重新初始化訂閱。
如果未在發佈保留期限(預設為336小時)內同步訂閱,則訂閱將過期,並由在發佈伺服器上運行的過期訂閱清理作業刪除。必須重新創建並同步訂閱。
如果推送訂閱過期,它將被完全刪除,但拉訂閱不會。您必須清除訂閱伺服器上的拉取訂閱。有關詳細信息,請參閱“刪除拉取訂閱”。
5,如何強制激活訂閱
某些情況下,訂閱端斷開超過設置的分發日誌最大保留期限之後,訂閱將會被標記為inactive,需要 must be reinitialized,此時可以強制“激活”訂閱,參考步驟如下:
1. 執行Select * from MSsubscriptions 定位到過期的訂閱
2. 使用如下的語句重置MSsubscriptions表. 使用 publisher_id, publisher_db, publication_id, subscriber_id and subscriber_db來激活訂閱
update distribution..MSsubscriptions set status=2 where publisher_id='x' andpublisher_db='x' and publication_id='x' and subscriber_id='x' and subscriber_db='x'
上述訂閱狀態status欄位的說明:
0 = Inactive
1 = Subscribed
2 = Active
另外請註意:即便是成功激活了訂閱,但是由於分發庫distrubution清理掉了過期的日誌,導致部分日誌不會傳遞到訂閱端,仍舊可能存在數據不一致的情況。
6,如何自動跳過事務複製錯誤,避免一條錯誤導致整個複製中斷
正如MySQL的主從複製中設置自動跳過複製錯誤一樣,SQLServer也可以設置在事務複製的過程中,如果遇到特定的錯誤(2061,2627,20598)會自動跳過而不至於導致整個複製中斷,同時SQLServer將遇到的錯誤信息寫入distribution.dbo.MSrepl_errors表中,可以通過監控手段來發現錯誤並修正錯誤。
2601:Cannot insert duplicate key row in object '%.*ls' with unique index '%.*ls'.)
2627 :Violation of %ls constraint '%.*ls'. Cannot insert duplicate key in object '%.*ls'.)
20598:The row was not found at the Subscriber when applying the replicated command
參考:https://learn.microsoft.com/en-us/previous-versions/sql/sql-server-2008-r2/ms151331(v=sql.105)
右鍵分發屬性,打開profile defaults按鈕,打開agent profile,default agent profile是預設的配置文件,選擇一個系統定義好的模版,其中continue on data consistency errrors模版是跳過常規的複製錯誤配置文件,勾選後點擊change Existing Agents按鈕更新分發代理的配置文件模版。
參考鏈接:
https://www.sanssql.com/2008/05/error-in-replicationsubscriptions-have.html
https://community.dynamics.com/blogs/post/?postid=319c904d-3673-42b5-9452-3bf373f3c391
https://www.techdevops.com/Article.aspx?CID=105
https://www.sqlservercentral.com/steps/stairway-to-sql-server-replication-level-4-transactional-replication-the-subscriber