Replication的犄角旮旯(三)--聊聊@bitmap
原文:Replication的犄角旮旯(三)--聊聊@bitmap

《Replication的犄角旮旯》系列导读

Replication的犄角旮旯(一)--变更订阅端表名的应用场景

Replication的犄角旮旯(二)--寻找订阅端丢失的记录

Replication的犄角旮旯(三)--聊聊@bitmap

Replication的犄角旮旯(四)--关于事务复制的监控

Replication的犄角旮旯(五)--关于复制identity列

Replication的犄角旮旯(六)-- 一个DDL引发的血案(上)(如何近似估算DDL操作进度)

Replication的犄角旮旯(七)-- 一个DDL引发的血案(下)(聊聊logreader的延迟)

Replication的犄角旮旯(八)-- 订阅与发布异构的问题

Replication的犄角旮旯(九)-- sp_setsubscriptionxactseqno,赋予订阅活力的工具

---------------------------------------华丽丽的分割线--------------------------------------------

关于replication中的bitmap,貌似介绍的文档不多;本文将从对此参数做一初步的简析,并介绍如何利用这个参数处理一些特定环境下的问题;

再次强调,本方法虽多次经受验证无误,但多次被MS supporter们建议不要尝试使用此方法,还望各位DBA三思!

先来看看@bitmap在哪里出现

  我们先创建一个表的复制订阅,表结构如下

 1 USE [test_aaa]
 2 GO
 3
 4 /****** Object:  Table [dbo].[test_b]    Script Date: 2014/1/23 16:12:28 ******/
 5 SET ANSI_NULLS ON
 6 GO
 7
 8 SET QUOTED_IDENTIFIER ON
 9 GO
10
11 SET ANSI_PADDING ON
12 GO
13
14 CREATE TABLE [dbo].[test_b](
15     [id1] [int] NOT NULL,
16     [id2] [int] NOT NULL,
17     [id3] [int] NOT NULL,
18     [id4] [int] NOT NULL,
19     [name] [varchar](10) NULL,
20     [remark1] [varchar](100) NULL,
21     [remark2] [varchar](100) NULL,
22     [remark3] [varchar](100) NULL,
23     [remark4] [varchar](100) NULL,
24  CONSTRAINT [pk_id1_id2_id3_id4] PRIMARY KEY CLUSTERED
25 (
26     [id1] ASC,
27     [id2] ASC,
28     [id3] ASC,
29     [id4] ASC
30 )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
31 ) ON [PRIMARY]
32
33 GO
34
35 SET ANSI_PADDING OFF
36 GO

View Code

  到订阅库的存储过程中,找到sp_MSupd_dbotest_b,生成脚本

 1 USE [test_byxl1]
 2 GO
 3 /****** Object:  StoredProcedure [dbo].[sp_MSupd_dbotest_b]    Script Date: 2014/1/23 14:28:46 ******/
 4 SET ANSI_NULLS ON
 5 GO
 6 SET QUOTED_IDENTIFIER ON
 7 GO
 8 ALTER procedure [dbo].[sp_MSupd_dbotest_b]
 9     @c1 int = NULL,
10     @c2 int = NULL,
11     @c3 int = NULL,
12     @c4 int = NULL,
13     @c5 varchar(10) = NULL,
14     @c6 varchar(100) = NULL,
15     @c7 varchar(100) = NULL,
16     @c8 varchar(100) = NULL,
17     @c9 varchar(100) = NULL,
18     @pkc1 int = NULL,
19     @pkc2 int = NULL,
20     @pkc3 int = NULL,
21     @pkc4 int = NULL,
22     @bitmap binary(2)
23 as
24 begin
25     if (substring(@bitmap,1,1) & 1 = 1) or
26        (substring(@bitmap,1,1) & 2 = 2) or
27        (substring(@bitmap,1,1) & 4 = 4) or
28        (substring(@bitmap,1,1) & 8 = 8)
29     begin
30         update [dbo].[test_b]
31         set  [id1] = case substring(@bitmap,1,1) & 1 when 1 then @c1 else [id1] end,
32              [id2] = case substring(@bitmap,1,1) & 2 when 2 then @c2 else [id2] end,
33              [id3] = case substring(@bitmap,1,1) & 4 when 4 then @c3 else [id3] end,
34              [id4] = case substring(@bitmap,1,1) & 8 when 8 then @c4 else [id4] end,
35              [name] = case substring(@bitmap,1,1) & 16 when 16 then @c5 else [name] end,
36              [remark1] = case substring(@bitmap,1,1) & 32 when 32 then @c6 else [remark1] end,
37              [remark2] = case substring(@bitmap,1,1) & 64 when 64 then @c7 else [remark2] end,
38              [remark3] = case substring(@bitmap,1,1) & 128 when 128 then @c8 else [remark3] end,
39              [remark4] = case substring(@bitmap,2,1) & 1 when 1 then @c9 else [remark4] end
40         where [id1] = @pkc1   and [id2] = @pkc2   and [id3] = @pkc3   and [id4] = @pkc4
41         if @@rowcount = 0
42             if @@microsoftversion>0x07320000
43                 exec sp_MSreplraiserror 20598
44     end
45     else
46     begin
47         update [dbo].[test_b]
48         set [name] = case substring(@bitmap,1,1) & 16 when 16 then @c5 else [name] end,
49             [remark1] = case substring(@bitmap,1,1) & 32 when 32 then @c6 else [remark1] end,
50             [remark2] = case substring(@bitmap,1,1) & 64 when 64 then @c7 else [remark2] end,
51             [remark3] = case substring(@bitmap,1,1) & 128 when 128 then @c8 else [remark3] end,
52             [remark4] = case substring(@bitmap,2,1) & 1 when 1 then @c9 else [remark4] end
53         where [id1] = @pkc1   and [id2] = @pkc2   and [id3] = @pkc3   and [id4] = @pkc4
54         if @@rowcount = 0
55             if @@microsoftversion>0x07320000
56                 exec sp_MSreplraiserror 20598
57     end
58 end   

View Code

  看到这么多@bitmap,是不是有种升仙的感觉?

  @bitmap 是binary类型,即二进制串;简单来说,它是用来表示所操作的字段位置的参数,通过@bitmap,分发代理从distribution.dbo.msrepl_commands中读取命令时(update操作),才会知道哪些列进行了更新;

  我们先来解析一下这个存储过程;

1、根据表结构的code,我们知道这个表共有9个字段,其中id1~id4被定义为联合主键;

由于binary(1)表示1个字节(8位的2进制),因此我们表示9个字段的@bitmap就只能用binary(2)来容纳了;

  其次,有的童鞋说,他们看到的update存储过程只有一个程序段,而我的例子中有两部分(29行~44行、46行~57行)。这个是由于存在联合主键造成的;即当被订阅的表中含有联合主键(2个或以上的字段一同作为主键)的时候才会出现两段代码,前者是更新主键列,后者则是更新非主键列;

2、根据更新列的位置不同,@bitmap中的对应的值也不同;

   substring(@bitmap,1,1) & 1 = 1 表示第一列有更新;

 substring(@bitmap,1,1) & 2 = 2 表示第二列有更新;

   substring(@bitmap,1,1) & 4 = 4 表示第三列有更新;

以此类推

   substring(@bitmap,1,1) & 128 = 128 表示第八列有更新;

那第九位呢?  =256么?  由于1个字节只有8位,而128=2^7,当第九位出现时就要进位了

   substring(@bitmap,2,1) & 1 = 1

怎么样,不难理解吧?

定义4个字段的联合主键只是为了举例说明的时候方便一些,实际的生产环境中可能不太经常能遇到;

再来看一下@bitmap在哪里可以获取到呢?我先更新一条记录,更新之前先关闭相应的分发代理(此处不需要分发命令应用到订阅端)

我们去distribution里看看具体的分发命令(具体做法请见《Replication的犄角旮旯(二)--寻找订阅端丢失的记录》)

从命令中我们可以看出,更新的列位置为第5(name)、7(remark2)、8(remark3)列,按照二进制的表示方法为(注意反取,即←表示第1至第9位)

0 1101 0000

由于第九位没有更新,因此为0,所以bitmap就是 1101 0000,换成十六进制就是0xD0,由于bitmap超出1个字节,因此后面再补0,就是我们看到的0xd000了

可能看到这里,有些童鞋会说,这太麻烦了,遇到一个很宽的表,光数逗号就数死了……尽管我们明白逗号是为了分割字段的,但系统为什么会这样生成呢,这个问题可以参考:http://msdn.microsoft.com/zh-cn/library/ms152489%28v=sql.120%29.aspx

这个和article的属性,调用订阅端存储过程方式有关(SCALL),这个不是本文的重点,在此不做赘述;

根据上面的算法,我们就可以知道,当我们要更新一个表时,可以根据更新列的位置,推算出实际的bitmap值,但这又有什么用呢?

-------------------------------------我是华丽丽的分割线-------------------------------------

应用场景:一个表(还是说商品表吧,比较典型),保存商品信息、简介等内容,都是varchar(max)或text类型;商家在促销活动前通常会大批量的更新这些内容(比如加个促销活动介绍等等),更新大字段是复制环境中最头疼的问题;

由于一条复制命令有长度限制(1K左右),如果一条更新记录中的更新内容过大,就会被拆分成多条命令写到msrepl_commands中(我曾经碰到过1条记录的更新操作被拆成100个复制命令),如果高峰时期有用户大量的进行这种操作,那作为DBA就可以升级为“张三疯”了;

这时候我们就可以根据具体的update命令(一般除了更新必要的字段外,还会捎带更新updatetime这样的时间戳,具体就去找研发兄弟们要吧),计算出相应的bitmap,然后在相应的存储过程中加个判断,屏蔽掉这样的操作;

具体操作就是,在sp_MSupd_dbotest_b这里的第24、25行之间加上

if @bitmap=0xd000

return;

再打开分发代理,这样就屏蔽了@bitmap=0xd000的全部操作;

按照前面的操作,并没有进行下面的更新

而我在此之后又从发布服务器insert了一条主键为2,2,2,2的记录,以证明该操作在update之后已经传到了订阅端,而update被屏蔽了;

需要注意的是,由于按位操作是绝对严格,对于只更新column1和同时更新column1、column2将产生不同的bitmap,操作时一定要谨慎;

posted on 2015-02-12 17:14 NET未来之路 阅读(...) 评论(...) 编辑 收藏

转载于:https://www.cnblogs.com/lonelyxmas/p/4288532.html

Replication的犄角旮旯(三)--聊聊@bitmap相关推荐

  1. Replication的犄角旮旯(五)--关于复制identity列

    Replication的犄角旮旯(五)--关于复制identity列 原文:Replication的犄角旮旯(五)--关于复制identity列 <Replication的犄角旮旯>系列导 ...

  2. Replication的犄角旮旯(一)--变更订阅端表名的应用场景

    原文:Replication的犄角旮旯(一)--变更订阅端表名的应用场景 <Replication的犄角旮旯>系列导读 Replication的犄角旮旯(一)--变更订阅端表名的应用场景 ...

  3. Replication的犄角旮旯(二)--寻找订阅端丢失的记录

    Replication的犄角旮旯(二)--寻找订阅端丢失的记录 原文:Replication的犄角旮旯(二)--寻找订阅端丢失的记录 <Replication的犄角旮旯>系列导读 Repl ...

  4. Replication的犄角旮旯(四)--关于事务复制的监控

    原文:Replication的犄角旮旯(四)--关于事务复制的监控 <Replication的犄角旮旯>系列导读 Replication的犄角旮旯(一)--变更订阅端表名的应用场景 Rep ...

  5. Veeam Backup Replication试用(三):配置备份(Backup Job)与恢复(Restore)

    近期veeam 9.5出来了,尝试安装使用,找到老管网络日志相关的文档,分享一下. 转自老管网络日志http://guanjianfeng.com/archives/1159347 ========= ...

  6. 将Roaring Bitmap序列化为JSON

    近期在实现一个数据结构时使用到了位图索引(bitmap index)[1],本文就来粗浅聊聊位图(bitmap). 一. 什么是bitmap 位图索引使用位数组(bit array,也有叫bitset ...

  7. Android源码解析之Bitmap占用内存正确的计算公式 你知道吗

    Bitmap 前言 Bitmap简介 像素存储方式 图片压缩格式 Bitmap内存计算 获取Bitmap所占内存 计算所占内存 举例 Bitmap.getAllocationByteCount Bit ...

  8. Bitmap类01_浅探

    Bitmap类解析 Bitmap类是对图像进行处理的类,可以获取图像信息,进行图像颜色变换等操作 在安卓中,Bitmap指的是一张图片,可以是 .png 或者 .jpg 等其他常见的图像格式 参考AP ...

  9. 探索 Bitmap 高性能使用姿势

    前段时间看到一篇图片加载相关的文章,非常全地介绍了 Bitmap 的内存.加载速度相关的使用姿势,受益颇多,得到作者允许后分享给小伙伴们一起学习! 本文作者:暴打小女孩 原文地址:https://li ...

最新文章

  1. 只需4秒,这个算法就能鉴别你的LV是真是假
  2. 网络编程学习笔记(服务器端进程终止)
  3. 人工智能终于能像人类一样学习,并通过了图灵测试
  4. 《大话数据结构》第9章 排序 9.4 简单选择排序
  5. Linux系统入门之如何安装Linux系统
  6. 链表相连与拷贝时的内存变化
  7. IE、Chrome、Firefox 三大浏览器对比
  8. discuz uc_server 配置登录
  9. Odin学习1 属性框标签
  10. Nachi机器人TCP通讯
  11. CSS-线性渐变无畸变-环形普通进度条-环形能量块进度条-局部环形普通进度条
  12. web前端——qq登录界面
  13. 二维码:Data Matrix和QRCode
  14. Elasticsearch:使用 Filebeat 从 Node.js Web 应用程序提取日志
  15. Vitalik Buterin:我的 40 升背包旅行指南
  16. 鼠标键盘与计算机无法连接,蓝牙鼠标/键盘同时提示已配对 但是永远无法连接上...
  17. uni-app 对照设计稿还原不同屏幕像素适配(iPhone X)
  18. RHCE 22个考点
  19. 计算机与算盘有什么区别
  20. Linux 设备驱动篇之I2c设备驱动

热门文章

  1. 呼叫中心客服交流三大法宝
  2. Linux 虚拟机配置-network is unreachable
  3. Python 中xrange和range区别
  4. 记录一次SQL查询语句
  5. 用Linux命令行实现删除和复制指定类型的文件
  6. lucene学习之helloworld(简单实例)
  7. ESP定律手工脱壳步骤
  8. oauth2.0 学习案例demo_Vue3教程:用 Vue3 开发小程序,这里有一份实际的代码案例!...
  9. mit许可证_MIT许可证的神秘历史
  10. scrum项目协作是什么_什么是小型Scrum?