首页 > 开发 > 综合 > 正文

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

2024-07-21 02:51:01
字体:
来源:转载
供稿:网友
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 GO10 11 SET ANSI_PADDING ON12 GO13 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] ASC30 )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 GO34 35 SET ANSI_PADDING OFF36 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 as24 begin   25     if (substring(@bitmap,1,1) & 1 = 1) or26        (substring(@bitmap,1,1) & 2 = 2) or27        (substring(@bitmap,1,1) & 4 = 4) or28        (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] end40         where [id1] = @pkc1   and [id2] = @pkc2   and [id3] = @pkc3   and [id4] = @pkc4 41         if @@rowcount = 042             if @@microsoftversion>0x0732000043                 exec sp_MSreplraiserror 20598 44     end   45     else46     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] end53         where [id1] = @pkc1   and [id2] = @pkc2   and [id3] = @pkc3   and [id4] = @pkc4 54         if @@rowcount = 055             if @@microsoftversion>0x0732000056                 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的犄角旮旯(二)--寻找订阅端丢失的记录》)

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表