zoukankan      html  css  js  c++  java
  • 我了解的数据库事务复制

    事务复制

    事务复制的基本机制,在联机文档上也有介绍。

    基本原理


     

    如图,主要依靠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_commandsMSrepl_transactions2个表中。然后就会使用过程sp_repldone标记事务已经被复制。

     

    SELECT spid,program_name FROM sys.sysprocesses WHERE spid IN( 57,55)

     

    sql server中查询sys.sysprocesses 2spid 会发现program_name='Repl-LogReader-0-p1-9

    也就是log reader agentsql server 上有2个会话一个负责读,一个负责写。这样Log Reader Agent的一次读取完成。

    Distribution Agent


    Log 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,这个字段表示现在订阅已经应用到了那个事务。奇特的事情又出现,会发现有2update语句。不知道是不是为了版本兼容。

    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完成一次分发。

     

  • 相关阅读:
    css和js实现硬件加速渲染自定义滚动条
    入驻博客园
    原生JS实现动态折线图
    纯JS自定义网页滚动条
    Unity实现代码控制音频播放
    MVC实现修改数据
    JS实现将二维数组生成到页面上
    JS实现页面计时
    多中方式,实现斐波那契数列
    算法题
  • 原文地址:https://www.cnblogs.com/Amaranthus/p/4271522.html
Copyright © 2011-2022 走看看