事務復制的基本機制,在聯機文檔上也有介紹。
基本原理如圖,主要依靠2個代理,1.日志讀取代理(log reader agent),2.分發代理(distribution agent)。
其中log reader agent,負責從發布數據庫上讀取日志并且寫入到分發數據庫(distribution)中。然后distribution agent負責從distribution讀取數據并且寫入到訂閱中。
Log Reader Agent開PRofiler,使用tsql模板即可。在已經有復制環境的狀態下,對發布項目執行:
BEGIN TRAN
go
INSERT INTO dbo.rename_sc DEFAULT VALUES
GO 10
COMMIT
最主要的部分:
如圖,Log Reader Agent使用會話55去發布庫的日志上讀取事務,如果發現有需要分發的,那么會調用sp_MSadd_replcmds,這個存儲過程會把抓到的指令存放到dbo.MSrepl_commands和MSrepl_transactions2個表中。然后就會使用過程sp_repldone標記事務已經被復制。
SELECT spid,program_name FROM sys.sysprocesses WHERE spid IN( 57,55)
在sql server中查詢sys.sysprocesses 這2個spid 會發現program_name='Repl-LogReader-0-p1-9
也就是log reader agent在sql server 上有2個會話一個負責讀,一個負責寫。這樣Log Reader Agent的一次讀取完成。
Distribution AgentLog Reader Agent寫入完之后就是有Distribution Agent 把事務應用到訂閱庫。
在存儲過程sys.sp_MSget_repl_commands對表dbo.MSrepl_commands讀取,之后就是在訂閱服務器上面運行sp_MSins命令。
仔細觀察其實不難發現msrepl_command表中存的是明碼,通過和sp_browsereplcmds對比就能發現,那么也就是說其實在插入MSrepl_commands的時候就已經知道了。
但是這里有個問題Agent是怎么知道要調用這個存儲過程的。
在這里會注意到有2個不同的會話在處理,一個負責讀,一個負責寫入,其中65負責從分發庫中讀取,51負責應用到訂閱庫
SELECT spid,program_name FROM sys.sysprocesses WHERE spid IN( 65 ,51)
最后會修改訂閱服務器中的MSreplication_subscriptions中的一些字段,其中最終要的是timestamp,這個字段表示現在訂閱已經應用到了那個事務。奇特的事情又出現,會發現有2個update語句。不知道是不是為了版本兼容。
UPDATE MSreplication_subscriptions
SET transaction_timestamp = CAST(@P1 AS BINARY(15))
+ CAST(SUBSTRING(transaction_timestamp, 16, 1) AS BINARY(1)) ,
"time" = @P2
WHERE UPPER(publisher) = UPPER(@P3)
AND publisher_db = @P4
AND publication = @P5
AND subscription_type = 1
AND( SUBSTRING(transaction_timestamp, 16, 1) = 0
OR DATALENGTH(transaction_timestamp) < 16
)
UPDATE MSreplication_subscriptions
SET transaction_timestamp = CAST(@P1 AS BINARY(15))
+ CAST(CASE DATALENGTH(transaction_timestamp)
WHEN 16
THEN ISNULL(SUBSTRING(transaction_timestamp, 16, 1), 0)
ELSE 0
END AS BINARY(1)) ,
"time" = @P2
WHERE UPPER(publisher) = UPPER(@P3)
AND publisher_db = @P4
AND publication = @P5
AND subscription_type = 1
Distribution Agent完成一次分發。
新聞熱點
疑難解答