SQLServer 事務複製在發佈端(publication)和訂閱端(subscription)對應的資料庫還原之後複製異常問題的解決

来源:https://www.cnblogs.com/wy123/p/18330818
-Advertisement-
Play Games

書接上文,在一個正常的事務複製環境中,如果發生了資料庫還原,事務複製會不會出問題,出問題之後又如何恢復,如果在不刪除訂閱發佈重建的情況下,如何在現有基礎上修複事務複製的異常,這個問題可以分為兩部分看: 1,如果publisher資料庫發生了還原操作,事務複製會出現什麼異常,該如何恢復? 2,如果是s ...


 

書接上文,在一個正常的事務複製環境中,如果發生了資料庫還原,事務複製會不會出問題,出問題之後又如何恢復,如果在不刪除訂閱發佈重建的情況下,如何在現有基礎上修複事務複製的異常,這個問題可以分為兩部分看:

1,如果publisher資料庫發生了還原操作,事務複製會出現什麼異常,該如何恢復?

2,如果是subscription資料庫發生了還原操作,事務複製會不會出現什麼異常?

 

還原發佈端資料庫的場景

首先看第一種情況,如果publisher資料庫發生了還原操作,由事務複製的架構可以發現,如果出現問題,此時問題一定會出現在publication和distribution之間,因為數據源(publication)發生了變化。

 

首先是一個正常的事務複製環境(SQL1作為publisher,SQL2作為distrubutor,SQL2,SQL3同時作為Subscriber),此時複製狀態完全正常。

嘗試用備份恢複發布資料庫(SQL1上的DB04庫)

use master
GO
ALTER DATABASE [DB04] SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
GO
RESTORE DATABASE [DB04] FROM DISK = N'C:\tmp\DB04_full_20240727.bak' 
WITH FILE = 1,REPLACE,  
MOVE N'Db04' TO N'C:\Program Files\Microsoft SQL Server\MSSQL15.MSSQLSERVER\MSSQL\DATA\Db04.mdf', 
MOVE N'Db04_log' TO N'C:\Program Files\Microsoft SQL Server\MSSQL15.MSSQLSERVER\MSSQL\DATA\Db04_log.ldf', 
NOUNLOAD, STATS = 5, norecovery;
GO
restore database DB04 from disk = 'C:\tmp\DB04_20240727_log1.trn';
GO

當完成恢復後,實物複製開始出現異常

1,通過複製監控面板看到複製開始異常

2,查看log reader agent的狀態,開始出現異常

3,找到對應的log reader agent對應的job

詳細日誌如下:

2024-07-29 10:13:33.536 OLE DB DISTOLE 'SQL2': select datasource, srvid from master..sysservers where ltrim(substring(reverse(ltrim(substring(reverse(srvname),charindex(',',reverse(srvname))+1,len(srvname)))),charindex(':',srvname)+1,len(srvname))) = N'SQL1' collate Latin1_General_CI_AI
2024-07-29 10:13:33.537 Status: 4096, code: 20024, text: 'Initializing'.
2024-07-29 10:13:33.537 The agent is running. Use Replication Monitor to view the details of this agent session.
2024-07-29 10:13:33.537 OLE DB DISTOLE 'SQL2': sp_MSget_last_transaction @publisher_id = 2, @publisher_db = N'DB04', @for_truncate = 0x0
2024-07-29 10:13:33.538 OLE DB DISTOLE 'SQL2': sp_MSquery_syncstates 2, N'DB04'
2024-07-29 10:13:33.539 OLE DB DISTOLE 'SQL2': sp_MSget_last_transaction @publisher_id = 2, @publisher_db = N'DB04', @for_truncate = 0x1
2024-07-29 10:13:33.539 Publisher: {call sp_repldone ( 0x00000029000002380003, 0x00000029000002380003, 0, 0)}
2024-07-29 10:13:33.556 Status: 0, code: 20011, text: 'The process could not execute 'sp_repldone/sp_replcounters' on 'SQL1'.'.
2024-07-29 10:13:33.556 The process could not execute 'sp_repldone/sp_replcounters' on 'SQL1'.
2024-07-29 10:13:33.556 Status: 0, code: 9003, text: 'The log scan number (41:568:3) passed to log scan in database 'DB04' is not valid. This error may indicate data corruption or that the log file (.ldf) does not match the data file (.mdf). If this error occurred during replication, re-create the publication. Otherwise, restore from backup if the problem results in a failure during startup.'.
2024-07-29 10:13:33.556 Status: 0, code: 22017, text: 'The process could not set the last distributed transaction.'.
2024-07-29 10:13:33.556 Status: 0, code: 22037, text: 'The process could not execute 'sp_repldone/sp_replcounters' on 'SQL1'.'.
2024-07-29 10:13:33.556 Disconnecting from OLE DB DISTOLE 'SQL2'

錯誤的關鍵是:The process could not execute 'sp_repldone/sp_replcounters' on 'SQL1'。

參考這裡https://repltalk.com/2010/02/19/the-process-could-not-execute-sp_repldonesp_replcounters/
If an old backup was restored on top of published database then use sp_replrestartIf going back to the most recent transaction log backup is not an option then execute sp_replrestart  on publisher in published database. This stored procedure is used when the highest log sequence number (LSN) value at the Distributor does match the highest LSN value at the Publisher.

This stored procedure will insert compensating LSNs (No Operation) in the publisher database log file till one the compensating LSN becomes more than the highest distributed LSN in distribution database for this published database. After this it inserts this new high LSN in the msrepl_transactions table in the distribution database and executes sp_repldone on published database to update the internal structures to mark a new starting point for log reader agent.

Ensure that the log reader agent is stopped and there is no incoming transactions on the published database, when this SP is executed.

由於資料庫被還原之後,相對還原之前的資料庫,還原之後的資料庫的事務日誌號(LSN)發生了“回退”,LSN是一個只讀的遞增序列號,比如還原之間資料庫的LSN到了10000,還原之後可能是8000或者其他小於10000的一個值,當日誌讀取代理器(log reader agent)在讀取日誌時,發現當前讀的日誌LSN比上一次讀的LSN還小(log reader agent在哪裡?其作用是什麼?為什麼要讀取事務日誌?參考上一篇文章),於是就開始報錯了。此時可以使用sp_repl_restart這個SP在發佈資料庫上執行,以修複以上錯誤,sp_replrestart的作用是,當分發伺服器上最高的日誌序列號 (LSN) 值與發佈伺服器上的最高 LSN 值不匹配時,將使用sp_replrestart。sp_replrestart詳細參考這裡

執行sp_replrestart之後,帶log reader agent重試執行之後,實物複製恢復正常。

 

訂閱端資料庫還原的場景

如果subscription資料庫發生了還原操作,由事務複製的架構可以發現,如果出現問題,此時問題一定會出現在distribution和subscription之間,因為目標資料庫(subscription)發生了變化。

 對於一個正常的實物複製環境,嘗試還原一個訂閱資料庫之後,觀察發生的現象。

1,如圖,當在還原訂閱庫的過程中,複製監控器開始出現retrying failed commend操作,其實不難理解,在訂閱庫還原的過程中,訂閱庫無法訪問,負責分發數據的job distribution agent也就無法正常工作

上述錯誤背後的distribution agent服務錯誤的詳細日誌,該日誌意味著,訂閱庫無法訪問,其實不難理解,訂閱庫在還原的過程中無法被外部訪問,因此distribution agent服務開始報錯。

以上在訂閱資料庫正常還原完成之後,distribution agent服務會自動重試(連接到訂閱庫進行數據傳輸),事務複製開始恢復正常。

此時需要註意,如果還原的資料庫相比未還原之前缺少數據,那麼在以後得複製過程中會出現無法找到匹配的數據錯誤(比如update的時候,主節點上有數據,但是訂閱端沒有對應的數據),類似於MySQL的1062主鍵衝突 , 或者1032數據未找到錯誤

總結

正常情況下,也就是還原前後資料庫的對象(表)沒有發生變更,對於如下兩種情況

1,如果publisher資料庫發生了還原操作,事務複製會出現什麼異常,該如何恢復?===》需要再發佈端的對應的資料庫上執行sp_replrestart命令來修複因還原資料庫導致的LSN變更

2,如果是subscription資料庫發生了還原操作,事務複製會不會出現什麼異常?===》不許出現特別的異常,只需要確保訂閱庫完成會還原後,對應的distributor agent正常啟動(經過重試錯誤)即可,不需要額外的處理

鑒於現實情況中存在各種複雜的其他因素,即便是事務複製被修複正常之後,也可能資料庫還原前後,數據上的某些差異導致複製無法正確進行,需要基於具體的細節進行診斷和修複。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 背景 今天在做項目的時候,總感覺運行不是很流暢,難道本地伺服器也有網路問題?一通操作下來,不出意外,沒解決。說來也巧,無意間的一瞥,竟讓我發現了問題所在——CPU 滿了。這就很不正常了,也沒運行什麼東西呀,不可能就這麼滿了。於是我就開始上網搜索,這是什麼原因導致的(這就是沒完成工作任務的理由?),功 ...
  • 第十五章 按鍵中斷實驗 1)實驗平臺:正點原子DNK210開發板 2)章節摘自【正點原子】DNK210使用指南 - CanMV版 V1.0 3)購買鏈接:https://detail.tmall.com/item.htm?&id=782801398750 4)全套實驗源碼+手冊+視頻下載地址:htt ...
  • 使用場景: 文件數量統計,在科研場景中,更多是用於檢驗、核對數據集的樣本數量,防止數據遺漏等意外情況。 常用命令: ls -l | grep "^-" | wc -l 作用:統計當前目錄下,文件的個數(不包括目錄/文件夾) ls -lR | grep "^-" | wc -l 作用:統計當前目錄下, ...
  • 本章將和大家分享Linux系統中的Vim編輯器。廢話不多說,下麵我們直接進入主題。 一、Vim 入門幫助 Vim 帶有完整的幫助文檔:進入 Vim 後輸入“:help”即可訪問 二、Vim 模式介紹 與大部分其它編輯器不同,進入 Vim 後,預設狀態下鍵入的字元並不會插入到所編輯的文件之中。Vim ...
  • SPI是嵌入式中使用比較廣泛的協議之一,本文從該協議的原理入手對其進行了詳細介紹,並結合STM32F103ZET主控晶元對其進行了說明,最後給出了兩個實例代碼demo供大家做參考。 ...
  • 本節內容 因為risc-v存在硬體特權級機制,我們又要實現一個可以使得應用程式工作在用戶級,使得操作系統工作在特權級.原因是要保證用戶態的應用程式不能隨意使用內核態的指令,要使用內核態的指令就必須通過操作系統來執行,這樣有了操作系統的控制和檢查,程式不會因為應用程式的問題導致整個操作系統都運行錯誤. ...
  • 本章將和大家分享Linux中的許可權控制。廢話不多說,下麵我們直接進入主題。 一、基礎知識 Linux作為一種多用戶的操作系統(伺服器系統),允許多個用戶同時登陸到系統上,並響應每個用戶的請求。 任何需要使用操作系統的用戶,都需要一個系統賬號,賬號分為:管理員賬號與普通用戶賬號。 在Linux中,操作 ...
  • 在現代軟體開發和部署中,Docker容器已成為一種流行的技術。然而,隨著容器的廣泛使用,數據保護和遷移也變得至關重要。本文將詳細介紹如何備份和遷移Docker容器,確保你的應用和數據在任何時候都是安全的。 一、為什麼需要備份和遷移Docker容器? 在某些情況下,你可能需要備份和遷移Docker容器 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...