在事务复制中,在发布服务器中执行了一个更新,例如:update orders set col=? Where ?,该操作产生大量的数据更新操作,在Log Reader存储事务和命令时,把该更新操作分解成多条command,每一个command只更新一条record,这些command 位于同一个Transaction中。发布服务器执行命令的基本单元是一个事务,或者一个子事务。当一个事务包含的命令过多时,可以把一个事务拆分成多个子事务,使得每个子事务只包含特定数量的command。这样,分发服务器在把一个子事务准备就绪后,就可以执行该子事务中的命令,循环该过程,最终把整个事务中完成。

在事务复制中,事务的顺序必须得到保证。事务在订阅者和发布者中的执行顺序是相同的,换句话说,订阅者接收事务的顺序和发布者执行事务的顺序是一致的。

Distribution Agent包含两个子进程,Reader和Writer。 Reader负责从distribution 数据库中读取数据,Writer负责将reader读取的数据写入到订阅数据库。Reader是通过 sys.sp_MSget_repl_commands 来读取Distribution数据库中挂起(pending)的命令和事务(读取Msrepl_transactions表和Msrepl_Commands表),并把读取到的数据存储到内部队列中。Writer从队列中顺序获取命令,通过执行以sp_MSupd…, sp_MSins…, sp_MSdel…为前缀的存储过程,把队列中的命令依次写入到subscriber,换句话说,把数据更新的命令在订阅服务器中重新执行一遍。

  1. CREATE PROCEDURE sys.sp_MSget_repl_commands
  2. @agent_id int,
  3. @last_xact_seqno varbinary(16),
  4. @get_count tinyint = 0, -- 0 = no count, 1 = cmd and tran (legacy), 2 = cmd only
  5. @compatibility_level int = 7000000,
  6. @subdb_version int = 0,
  7. @read_query_size int = -1

对Reader进行调优

案例:在Distribution Agent同步数据时,发现Subscriber中有很多Session处于 ASYNC_NETWORK_IO等待状态,该Session正在执行的sp是:sys.sp_MSget_repl_commands,正在执行的语句如下,这条查询用于返回Distribution Agent读取的Commands。

  1. select rc.xact_seqno, rc.partial_command, rc.type,
  2. rc.command_id, rc.command, rc.hashkey,
  3. -- extra columns for the PeerToPeer resultset
  4. -- originator_id, srvname, dbname, originator_publication_id, originator_db_version, originator_lsn
  5. NULL, NULL, NULL, NULL, NULL, NULL, rc.article_id
  6. from MSrepl_commands rc with (nolock, INDEX(ucMSrepl_commands))
  7. inner join dbo.MSsubscriptions s with (INDEX(ucMSsubscriptions))
  8. -- At end, we use the FASTFIRSTROW option which tends to force
  9. -- a nested inner loop join driven from MSrepl_commands
  10. ON (rc.article_id = s.article_id)
  11. where s.agent_id = @agent_id and
  12. rc.publisher_database_id = @publisher_database_id and
  13. rc.xact_seqno > @last_xact_seqno and
  14. rc.xact_seqno <= @max_xact_seqno and
  15. (rc.type & @snapshot_bit) <> @snapshot_bit and
  16. (rc.type & ~@snapshot_bit) not in ( 37, 38 )
  17. and (@compatibility_level >= 9000000
  18. or (rc.type & ~@postcmd_bit) not in (47))
  19. order by rc.xact_seqno, rc.command_id asc
  20. OPTION (FAST 1)

说明该Session返回的数据集太大,导致Writer不能及时读取Command,使得分发的时延增加。

1,查看正在分发的事务

通过SQL Server Profile抓取当前正在执行的SQL命令,从抓取的大量语句中发现,sp_MSget_repl_commands 一般只会用到前四个参数,第三个和第四个参数的值是固定不变的,分别是0和10000000。

  1. exec sp_MSget_repl_commands 74,0x0008ECE200307E10014C00000000,0,10000000

2,Distribution Agent 读取的Commnd数量

sys.sp_MSget_repl_commands 返回的Result Set的大小跟变量 @max_xact_seqno 有关

  1. rc.xact_seqno > @last_xact_seqno and rc.xact_seqno <= @max_xact_seqno

对变量 @max_xact_seqno 的赋值,是由 @read_query_size 参数控制的,在调用该sp时,其值是默认值-1。

下面代码表示 将 dbo.MSrepl_commands 最大的 xact_seqno 赋值给变量@max_xact_seqno,那么Distribution Agent 每次都会读取所有的Command。

  1. --Note4: The max_xact_seqno is calculated based on the @read_query_size parameter -
    -- this parameter limit the number of commands retrieved by this call. 
    if(@read_query_size <= 0)
  2. begin
  3. select @max_xact_seqno = max(xact_seqno) from MSrepl_commands with (READPAST)
  4. where
  5. publisher_database_id = @publisher_database_id and
  6. command_id = 1 and
  7. type <> -2147483611
  8. end
  9. else ....

3,是否可以修改参数 @read_query_size的值

明确为@read_query_size传递一个参数值,而不是使用默认值 -1,可以解决这个问题,但是该sp是系统存储过程,不能直接修改,而Distribution Agent profile中也没有参数能够控制Reader读取的Command数量。

┬_┬

遇到这种情况,就需要换种角度来思考,长时间出现ASYNC_NETWORK_IO,根本原因是一个Trasaction中包含的Command过多,而数据更新的速度跟不上。如果在源头把一个事务拆分成多个子事务,每个子事务可以很快地执行完成。

如果Log Reader将大事务拆分成多个小的Transaction写入到Distribution中,那么Distribution Reader很快地把commands读取,写入到in-memory queue中,进而 Distribution Writer很快把 Queued Commands 写入到Subscriber中,完成数据的一次同步。只要Distribution Reader的读取速度能够跟上Log Reader写入的速度,而Distribution Writer的写入速度也能跟上Distribution Reader的读取速度,这样Distribution Latency 就会很小。

参考文档:

Performance Tuning SQL Server Transactional Replication – Part 1

SQL Server复制系列4 – Transactional replication中如何跳过一个事务

发布订阅延迟故障排查案例:分发读进程延迟

Replication:Distribution Reader的更多相关文章

  1. Distribution1:Distribution Reader

    在transactional replication中,在publication中执行了一个更新,例如:update table set col=? Where ?,如果table中含有大量的数据行, ...

  2. Replication:distribution 中一直在运行 waitfor delay @strdelaytime 语句

    Replication 自动创建来一个 Job:Replication monitoring refresher for distribution,这个Agent执行一个sp: dbo.sp_repl ...

  3. Distribution2:Distribution Writer

    Distribution Writer 调用Statement Delivery 存储过程,将Publication的改变同步到Subscriber中.查看Publication Properties ...

  4. 简单的Windows Webcam应用:Barcode Reader

    原文:简单的Windows Webcam应用:Barcode Reader 在Windows上用WinForm创建一个Webcam应用需要用到DirectShow.DirectShow没有提供C#的接 ...

  5. 第八篇 Replication:合并复制-How it works

    本篇文章是SQL Server Replication系列的第八篇,详细内容请参考原文. 在这一系列的前几篇你已经学习了如何在多服务器环境中配置合并复制.这一篇将介绍合并代理并解释它在复制过程中扮演的 ...

  6. 【译】第八篇 Replication:合并复制-How it works

    本篇文章是SQL Server Replication系列的第八篇,详细内容请参考原文. 在这一系列的前几篇你已经学习了如何在多服务器环境中配置合并复制.这一篇将介绍合并代理并解释它在复制过程中扮演的 ...

  7. 第七篇 Replication:合并复制-订阅

    本篇文章是SQL Server Replication系列的第七篇,详细内容请参考原文. 订阅服务器就是复制发布项目的所有变更将传送到的服务器.每一个发布需要至少一个订阅,但是一个发布可以有多个订阅. ...

  8. 第五篇 Replication:事务复制-How it works

    本篇文章是SQL Server Replication系列的第五篇,详细内容请参考原文. 这一系列包含SQL Server事务复制和合并复制的详细内容,从理解基本术语和设置复制的方法,到描述它是如何工 ...

  9. 第四篇 Replication:事务复制-订阅服务器

    本篇文章是SQL Server Replication系列的第四篇,详细内容请参考原文. 订阅服务器就是复制发布项目的所有变更将传送到的服务器.每一个发布需要至少一个订阅,但是一个发布可以有多个订阅. ...

随机推荐

  1. OKGo vs RxHttpUtils ...

    jeasonlzy/okhttp-OkGohttps://github.com/jeasonlzy/okhttp-OkGo Android OkGo基本操作https://www.jianshu.co ...

  2. Spring cloud简单学习总结

    微服务简介 一.spring boot和spring cloud 的关系 spring boot来写各个拆分出来的微服务,spring  cloud把各个微服务联系起来,比如各个微服务通过eurke找 ...

  3. Reactive-MongoDB 异步 Java Driver 解读

    一.关于 异步驱动 从3.0 版本开始,MongoDB 开始提供异步方式的驱动(Java Async Driver),这为应用提供了一种更高性能的选择.但实质上,使用同步驱动(Java Sync Dr ...

  4. Robot Framework常用关键字

    虽然通过RIDE提供"填表"一样的写测试用例的方式.但它却支持强大的关键字功能,以及可以开发关键字的扩展能力. Comment 注释功能,也可以使用python中的"#& ...

  5. VSCode在Ubuntu下快捷键和Windows下不一致的解决办法

    Windows下切换前一次和后一次光标位置,用的快捷键是Alt+<-和Alt+->.很遗憾,Ubuntu下并不是这个快捷键.不清楚为什么VSCode不提供统一的快捷键,但对于我来说,我很想 ...

  6. Wordpress 设置中文语言包

    从官方安装的是英文版的,想要切换成中文语言包 1.修改项目目录下面的wp-config文件: 添加define(‘WPLANG’, ‘zh_CN’); 保存文件 2.进入站点控制板(dashboard ...

  7. php模板模式(template design)

    没有写停止条件,所以会一直运行哟. <?php /* The template design pattern defines the program skeleton of an algorit ...

  8. U-Boot的常用命令详解

    U-Boot还提供了更加详细的命令帮助,通过help命令还可以查看每个命令的参数说明.由于开发过程的需要,有必要先把U-Boot命令的用法弄清楚.接下来,根据每一条命令的帮助信息,解释一下这些命令的功 ...

  9. 201871020225-牟星源 《面向对象程序设计(java)》课程学习进度条

    <2019面向对象程序设计(java)课程学习进度条> 周次 (阅读/编写)代码行数 发布博客量/评论他人博客数量 课余学习时间(小时) 学习收获最大的程序 阅读或编译让我 第一周 25/ ...

  10. MySQL 的各种 join

    table th:first-of-type { width: 200px; } join 类型 备注 left [outer] join right [outer] join union [all ...