《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 GOView 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 endView 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的犄角旮旯(二)--尋找訂閱端丟失的記錄》)
新聞熱點
疑難解答