原文:SqlServer 禁止架构更改的复制中手动修复使发布和订阅中分别增加的字段同步

由于之前的需要,禁止了复制架构更改,以至在发布中添加一个字段,并不会同步到订阅中,而现在又在订阅中添加了一个同名字段,怎么使这发布和订阅的两个字段建立同步关系呢?

下面就测试更改:此次发布类型为事务复制的可更新订阅,其他类型的发布没有测试。

首先建立事务复制的可更新订阅,建立好之后。

在发布创建一张测试表:

CREATE TABLE [dbo].[DemoTab](
[Guid] [uniqueidentifier] NOT NULL,
[SID] [varbinary](85) NOT NULL,
[Title] [nvarchar](100) NOT NULL,
CONSTRAINT [PK_DemoTab] PRIMARY KEY CLUSTERED ([SID] ASC,[Guid] ASC)
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[DemoTab] ADD CONSTRAINT [DF_DemoTab_Guid] DEFAULT (newsequentialid()) FOR [Guid]
GO
ALTER TABLE [dbo].[DemoTab] ADD CONSTRAINT [DF_DemoTab_SID] DEFAULT (suser_sid()) FOR [SID]
GO

将表添加发布,并初始化该表:

Exec sp_addarticle
@publication = 'publication'
, @article = N'DemoTab'
, @source_object = N'DemoTab'
, @source_owner = N'dbo'
, @schema_option = 0x0000000008037CDF
, @vertical_partition = N'true'
GO
Exec sp_refreshsubscriptions 'publication'
GO
Exec sp_startpublication_snapshot 'publication'
GO

分表在发布和订阅都测试,确认同步正常:

INSERT INTO [DemoTab](Guid,SID,Title) select NEWID(),SUSER_SID(),'test'
UPDATE [DemoTab] SET Title = 'KK'
DELETE FROM [DemoTab]

现在禁用 "复制架构更改"

也可以用脚本禁止:

--	禁止 "复制架构更改"
EXEC sp_changepublication @publication = N'publication', @property = N'replicate_ddl', @value = 0

现在分别在发布数据库和订阅数据库执行增加字段,因为架构不同步,所以并不会冲突。

ALTER TABLE dbo.[DemoTab] ADD TEST INT NULL

增加后,只要不对新增的列 test 操作,复制仍正常。但要禁止客户对该表进行操作,因为更改过程中涉及的对象要更改,别面出错!

首先介绍主要参考的3个存储过程,都在发布数据库执行.(注:可执行查看,但生成的脚本不要执行)

--订阅的所有同步存储过程.生成脚本在订阅库执行
EXEC sp_scriptpublicationcustomprocs N'publication' --发布中的冲突表.生成脚本在发布库执行
EXEC sp_scriptsubconflicttable @publication = 'publication', @article = 'DemoTab' --订阅触发器.生成脚本在订阅库执行
EXEC sp_script_synctran_commands @publication = 'publication', @article = 'DemoTab'

将新增的列添加到发布项目中(在发布数据库执行)

--查看发布列的信息
select name,column_id from sys.columns where object_id=object_id('DemoTab')
select artid from sysarticles where name='DemoTab'
select * from sysarticlecolumns where artid=1044

从上面可以知道,字段 [TEST]  的id=8 , 表 [DemoTab] 的发布项目编号 artid = 1044,当前字段[TEST]并未添加到发布表中,下面将该列添加到发布

insert into sysarticlecolumns select 1044,8,0,0,0

上面的语句执行后,可以在界面中看到该列已经添加进去。

现在执行上面所说的3个存储过程,在发布数据库执行。该存储过程生成订阅的同步存储过程,生成的脚本在订阅数据库执行(手动应用快照)

EXEC sp_scriptpublicationcustomprocs N'publication'
--
-- 来自数据库 'publisherdb'、发布 'publication' 的事务复制自定义过程:
-- ----
---- 项目 'DemoTab' 的复制自定义过程:
---- if object_id(N'[sp_MSins_dboDemoTab]', 'P') > 0
drop proc [sp_MSins_dboDemoTab]
go
if object_id(N'dbo.MSreplication_objects') is not null
delete from dbo.MSreplication_objects where object_name = N'sp_MSins_dboDemoTab'
go
create procedure [sp_MSins_dboDemoTab]
@c1 uniqueidentifier,@c2 varbinary(85),@c3 nvarchar(100),@c4 uniqueidentifier,@c5 int
as
begin
if not exists (select * from [dbo].[DemoTab]
where ( [SID] = @c2 and [Guid] = @c1 )
)
begin
insert into [dbo].[DemoTab](
[Guid]
,[SID]
,[Title]
,[msrepl_tran_version]
,[TEST]
)
values (
@c1
,@c2
,@c3
,@c4
,@c5
)
end
end
go
if columnproperty(object_id(N'dbo.MSreplication_objects'), N'article', 'AllowsNull') is not null
exec ('insert dbo.MSreplication_objects (object_name, publisher, publisher_db, publication, article, object_type)
values (+ N''sp_MSins_dboDemoTab'' , N''SZ1CARD1-DB'' , N''PlatformSync'' , N''publication'' , N''DemoTab'' ,''P'')')
go if object_id(N'[sp_MSupd_dboDemoTab]', 'P') > 0
drop proc [sp_MSupd_dboDemoTab]
go
if object_id(N'dbo.MSreplication_objects') is not null
delete from dbo.MSreplication_objects where object_name = N'sp_MSupd_dboDemoTab'
go
create procedure [sp_MSupd_dboDemoTab]
@c1 uniqueidentifier,@c2 varbinary(85),@c3 nvarchar(100),@c4 uniqueidentifier,@c5 int,@pkc1 uniqueidentifier,@pkc2 varbinary(85)
,@old_msrepl_tran_version uniqueidentifier
,@bitmap binary(1)
as
begin
if ( substring(@bitmap,1,1) & 1 = 1 or substring(@bitmap,1,1) & 2 = 2 )
begin
update [dbo].[DemoTab] set
[Guid] = case substring(@bitmap,1,1) & 1 when 1 then @c1 else [Guid] end
,[SID] = case substring(@bitmap,1,1) & 2 when 2 then @c2 else [SID] end
,[Title] = case substring(@bitmap,1,1) & 4 when 4 then @c3 else [Title] end
,[msrepl_tran_version] = case substring(@bitmap,1,1) & 8 when 8 then @c4 else [msrepl_tran_version] end
,[TEST] = case substring(@bitmap,1,1) & 16 when 16 then @c5 else [TEST] end
where [Guid] = @pkc1 and [SID] = @pkc2
and msrepl_tran_version = @old_msrepl_tran_version
end
else
begin
update [dbo].[DemoTab] set
[Title] = case substring(@bitmap,1,1) & 4 when 4 then @c3 else [Title] end
,[msrepl_tran_version] = case substring(@bitmap,1,1) & 8 when 8 then @c4 else [msrepl_tran_version] end
,[TEST] = case substring(@bitmap,1,1) & 16 when 16 then @c5 else [TEST] end
where [Guid] = @pkc1 and [SID] = @pkc2
and msrepl_tran_version = @old_msrepl_tran_version
end
end
go
if columnproperty(object_id(N'dbo.MSreplication_objects'), N'article', 'AllowsNull') is not null
exec ('insert dbo.MSreplication_objects (object_name, publisher, publisher_db, publication, article, object_type)
values (+ N''sp_MSupd_dboDemoTab'' , N''SZ1CARD1-DB'' , N''PlatformSync'' , N''publication'' , N''DemoTab'' ,''P'')')
go if object_id(N'[sp_MSdel_dboDemoTab]', 'P') > 0
drop proc [sp_MSdel_dboDemoTab]
go
if object_id(N'dbo.MSreplication_objects') is not null
delete from dbo.MSreplication_objects where object_name = N'sp_MSdel_dboDemoTab'
go
create procedure [sp_MSdel_dboDemoTab]
@pkc1 uniqueidentifier,@pkc2 varbinary(85)
,@msrepl_tran_version uniqueidentifier
as
begin
delete [dbo].[DemoTab]
where [Guid] = @pkc1 and [SID] = @pkc2
and msrepl_tran_version = @msrepl_tran_version
end
go
if columnproperty(object_id(N'dbo.MSreplication_objects'), N'article', 'AllowsNull') is not null
exec ('insert dbo.MSreplication_objects (object_name, publisher, publisher_db, publication, article, object_type)
values (+ N''sp_MSdel_dboDemoTab'' , N''SZ1CARD1-DB'' , N''PlatformSync'' , N''publication'' , N''DemoTab'' ,''P'')')
go

此存储过程生成应用于订阅的跟踪项目信息和同步触发器。 生成的脚本在订阅服务器的订阅数据库上执行。 此存储过程在发布服务器的发布数据库中执行。

EXEC sp_script_synctran_commands @publication = 'publication', @article = 'DemoTab'

if @@microsoftversion<0x07320000
raiserror('当发布服务器为 SQL Server 2000 或更高版本时,必须将订阅服务器升级到 SQL Server 2000 才能创建可更新订阅。',16, -1) if (@@microsoftversion >= 0x09000000)
begin
exec sp_addqueued_artinfo 1044
, N'DemoTab'
, N'publisher'
, N'publicationDB'
, N'publication'
, N'DemoTab'
, N'dbo'
, N'conflict_publication_DemoTab'
end if (@@microsoftversion < 0x09000000)
begin
exec sp_addqueued_artinfo 1044
, N'DemoTab'
, N'publisher'
, N'publicationDB'
, N'publication'
, N'DemoTab'
, N'dbo'
, N'conflict_publication_DemoTab'
, 0x000000000000000000000000000000000000000000000000000000000000008f
end if (@@microsoftversion >= 0x09000000)
begin
delete from MSsubscription_articlecolumns
where artid = 1044
and agent_id = (
select id from MSsubscription_agents
where update_mode > 0
and UPPER(publisher) = UPPER(N'publisher')
and publisher_db = N'publicationDB'
and publication = N'publication'
)
end if (@@microsoftversion >= 0x09000000)
begin
declare @agent_id_1044 int
select @agent_id_1044 = id
from MSsubscription_agents
where update_mode > 0
and UPPER(publisher) = UPPER(N'publisher')
and publisher_db = N'publicationDB'
and publication = N'publication' if @agent_id_1044 is not null
begin
insert MSsubscription_articlecolumns (agent_id, artid, colid)
values (@agent_id_1044, 1044, 1)
insert MSsubscription_articlecolumns (agent_id, artid, colid)
values (@agent_id_1044, 1044, 2)
insert MSsubscription_articlecolumns (agent_id, artid, colid)
values (@agent_id_1044, 1044, 3)
insert MSsubscription_articlecolumns (agent_id, artid, colid)
values (@agent_id_1044, 1044, 4)
insert MSsubscription_articlecolumns (agent_id, artid, colid)
values (@agent_id_1044, 1044, 8)
end
end if (@@microsoftversion >= 0x080002C0)
begin
exec sp_addsynctriggers
N'DemoTab'
, N'dbo'
, N'publisher'
, N'publicationDB'
, N'publication'
, N'sp_MSsync_ins_DemoTab_4'
, N'sp_MSsync_upd_DemoTab_4'
, N'sp_MSsync_del_DemoTab_4'
, N'sp_MScft_publication_DemoTab'
, N'dbo'
, N'null'
, N'null'
, N'null'
, 0x03
, 0
,1
,N'publisher'
, 2
end if (@@microsoftversion < 0x080002C0)
begin
exec sp_addsynctriggers
N'DemoTab'
, N'dbo'
, N'publisher'
, N'publicationDB'
, N'publication'
, N'sp_MSsync_ins_DemoTab_4'
, N'sp_MSsync_upd_DemoTab_4'
, N'sp_MSsync_del_DemoTab_4'
, N'sp_MScft_publication_DemoTab'
, N'dbo'
, N'null'
, N'null'
, N'null'
, 0x03
, 0
,1
,N'publisher'
end

订阅相关对象已经更改完成!接下来还得改发布中的一些对象!~

查看发布数据库中涉及的对象:

SELECT * FROM sysarticleupdates WHERE artid=(select artid from sysarticles where name='DemoTab')



对应d 对象,这些对象都需要更改!~

select
case
when object_id=427877337 then 'sync_ins_proc'
when object_id=443877394 then 'sync_upd_proc'
when object_id=459877451 then 'sync_del_proc'
when object_id=475877508 then 'sync_upd_tri'
when object_id=491877565 then 'conflict_tableid'
when object_id=539877736 then 'ins_conflict_proc'
else '' end as sysarticleupdates
,object_id,name
from sys.objects
where object_id in(427877337,443877394,459877451,475877508,491877565,539877736)

6 个对象,将逐个更改!(sp_MSsync_upd_trig_DemoTab_4 不需要更改)

1. 更改冲突表 conflict_publication_DemoTab

重新创建冲突表.在发布数据库执行,生成的脚本在发布数据库执行.

EXEC sp_scriptsubconflicttable @publication = 'publication', @article = 'DemoTab'
if object_id(N'[dbo].[conflict_publication_DemoTab]') is not null
begin DROP TABLE [dbo].[conflict_publication_DemoTab] end
CREATE TABLE [dbo].[conflict_publication_DemoTab](
[Guid] uniqueidentifier NOT NULL
,[SID] varbinary(85) NOT NULL
,[Title] nvarchar(100) NOT NULL
,[msrepl_tran_version] uniqueidentifier NOT NULL
,[TEST] int NULL
,origin_datasource nvarchar(255) NULL
,conflict_type int NULL
,reason_code int NULL
,reason_text nvarchar(720) NULL
,pubid int NULL
,tranid nvarchar(40) NULL
,insertdate datetime NOT NULL
,qcfttabrowid uniqueidentifier DEFAULT NEWID() NOT NULL
)
CREATE UNIQUE INDEX [cftind_publication_DemoTab]
ON [dbo].[conflict_publication_DemoTab]([SID], [Guid], tranid, qcfttabrowid)

重建表之后,object_id 不一样,sysarticleupdates 的冲突表id需要更改。

update sysarticleupdates
set conflict_tableid = (select object_id from sys.objects where object_id=object_id('conflict_publication_DemoTab'))
where artid=(select artid from sysarticles where name='DemoTab')

2.修改更新冲突表的存储过程

exec sp_helptext sp_MScft_publication_DemoTab



3. 更改发布中的存储过程

发布库这 3 个存储过程:sp_MSsync_del_DemoTab_4,sp_MSsync_ins_DemoTab_4,sp_MSsync_upd_DemoTab_4

这3 个存储过程分别被订阅数据库表的触发器调用,因此注意传参的位置.新字段[test]参数在[msrepl_tran_version]之后



trg_MSsync_del_DemoTab 调用存储过程 sp_MSsync_del_DemoTab_4

trg_MSsync_ins_DemoTab 调用存储过程 sp_MSsync_ins_DemoTab_4

trg_MSsync_upd_DemoTab 调用存储过程 sp_MSsync_upd_DemoTab_4

这3个存储改动的地方较多,但是都是更改相应的列。里面要加入参数,或者字段赋值等,字段test参考其他字段就行,参数只是改变个编号。

 [sp_MSsync_del_DemoTab_4]  增加传递的参数 @c5_old  INT ,修改一处位置如下。

[sp_MSsync_ins_DemoTab_4] 增加传递的参数 @c5  INT 

更改2处相同代码:

    insert into [dbo].[DemoTab](  [Guid] , [SID] , [Title] , [msrepl_tran_version] ,TEST )
values ( @c1 , @c2 , @c3 , @c4 ,@c5 )

更改1处代码:

sp_MSsync_upd_DemoTab_4 增加2个参数 @c6 int  ,,@c6_old int  ,更改几处脚本

参数位置参考订阅触发器 trg_MSsync_upd_DemoTab 中传递的位置 :@c1,@c2,@c3,@c4,@c6  ,@c1_old,@c2_old,@c3_old,@c4_old,@c6_old

注: 上面的参数应该都以触发器中的名称编号一样,不是@c5, 而是 @c6 ,避免以后再添加列时导致错乱!~上面的应该改!(刚忘记 了,就不回去改了)

注意这里,前8列获取第一个字节 substring(@bitmap,1,1) ,每列对应一个位,第5列为 00010000, 为16.注意改这里。

(更多参考 深入理解SQL Server 2005 中的 COLUMNS_UPDATED函数 )

发布对象更改完成!~

现在进行测试,分别在发布库和订阅库执行一遍,数据正常同步!~

INSERT INTO [DemoTab](Guid,SID,Title) select NEWID(),SUSER_SID(),'test'
UPDATE [DemoTab] SET Title = 'KK'
DELETE FROM [DemoTab] INSERT INTO [DemoTab](Guid,SID,Title,test) select NEWID(),SUSER_SID(),'test',0
UPDATE [DemoTab] SET test = 10
DELETE FROM [DemoTab] ALTER TABLE dbo.[DemoTab] DROP COLUMN TEST

最终删除该列 【test】,订阅库中也自动同步被删除!~同步正常!~试验结束!~

总结:

手动更改比较麻烦!~尤其是在发布库,没有找到相关自动生成的存储过程(觉得应该是有的),所以发布的对象一个个更改!~刚开始的时候,本人连订阅的对象都是一个个更改!~后来测试几次总结出这个顺序。

--发布库执行,将新增的字段添加到发布.
select name,column_id from sys.columns where object_id=object_id('DemoTab')
select artid from sysarticles where name='DemoTab'
select * from sysarticlecolumns where artid=1044 --发布库执行,生成的脚本在订阅执行.
EXEC sp_scriptpublicationcustomprocs N'publication'
EXEC sp_scriptsubconflicttable @publication = 'publication', @article = 'DemoTab'
EXEC sp_script_synctran_commands @publication = 'publication', @article = 'DemoTab' --发布库执行,修改发布相关对象
SELECT * FROM sysarticleupdates WHERE artid=

为什么要这样做?有时候有的表没有同步、有时某些对象被删除、或者原本不行同步,现在又同步了(如开始说明)。

这里还没完全测试,比如在发布和订阅的字段都有数据时,会不会也是同样处理?

本文出自“Hello.KK
(SQL Server)
”的博客,转载请务必保留此出处http://blog.csdn.net/kk185800961

SqlServer 禁止架构更改的复制中手动修复使发布和订阅中分别增加的字段同步的更多相关文章

  1. (转)SqlServer 数据库同步的两种方式 (发布、订阅),主从数据库之间的同步

    最近在琢磨主从数据库之间的同步,公司正好也需要,在园子里找了一下,看到这篇博文比较详细,比较简单,本人亲自按步骤来过,现在分享给大家. 在这里要提醒大家的是(为了更好的理解,以下是本人自己理解,如有错 ...

  2. SqlServer 数据库同步的两种方式 (发布、订阅),主从数据库之间的同步

    最近在琢磨主从数据库之间的同步,公司正好也需要,在园子里找了一下,看到这篇博文比较详细,比较简单,本人亲自按步骤来过,现在分享给大家. 在这里要提醒大家的是(为了更好的理解,以下是本人自己理解,如有错 ...

  3. GTID环境中手动修复主从故障一例(Error 1236/Error 1396)

      Preface       I got an replication error 1236 when I modified the password of a user without start ...

  4. GTID环境中手动修复主从故障一例(Error 1146)

      Preface       In my last test of pt-heartbeat,both of master and slave were out of disk.And the my ...

  5. SQLServer 中发布与订阅

    在对数据库做迁移的时候,会有很多方法,用存储过程,job,也可以用开源工具kettle,那么今天这些天变接触到了一种新的方法,就是SqlServer中自带的发布与订阅. 首先说明一下数据复制的流程.如 ...

  6. 发布与订阅SQLServer

    SQLServer 中发布与订阅 在对数据库做迁移的时候,会有很多方法,用存储过程,job,也可以用开源工具lettle,那么今天这些天变接触到了一种新的方法,就是SqlServer中自带的发布与订阅 ...

  7. node.js 中 events emitter 的实现(发布、订阅模式)

    const EventEmitter = require('events'); const myEmitter = new EventEmitter(); myEmitter.on('event', ...

  8. SqlServer Bug:复制架构更改参数(replicate_ddl)无效

    原文:SqlServer Bug:复制架构更改参数(replicate_ddl)无效 最近测试可更新订阅的架构更改问题,发现了一个 bug. 在复制中,当在发布数据库对发布数据库进行架构更改时,结构自 ...

  9. SQLServer 可更新订阅数据在线架构更改(增加字段)方案

    原文:SQLServer 可更新订阅数据在线架构更改(增加字段)方案 之前一直查找冲突发布和订阅数据不一致的原因,后来发现多少数据库升级引起,因为一直以来都是在发布数据库增加字段,订阅也会自动同步.在 ...

随机推荐

  1. IT增值服务-客户案例(三):合肥薪火科技,Java和P2P网络借贷系统开发指导

    客户整体情况: 合肥薪火科技,是安徽合肥一家主营微信开发和运营的中小企业,http://weimarket.cn/. 这家公司筹备.创立.曲折创业的经历,我一直有关注.因为2个老板,都是我的同学校友, ...

  2. 【t062】最厉害的机器人

    Time Limit: 1 second Memory Limit: 128 MB [问题描述] [背景] Wind设计了很多机器人.但是它们都认为自己是最强的,于是,一场比赛开始了~ [问题描述] ...

  3. Qt Roadmap for 2018(对3D有很多改进)

    When it comes to new features, we have many things ongoing related to graphics, so I’ll start with t ...

  4. Everything starts with a dream(A day has only 24 hours and these things take time,所以要抓紧)

    There is the famous quote: "Everything starts with a dream" and many years ago, Michael Va ...

  5. Javascript中eval解析的json的几种用法

    eval解析json字符串可用的三种方式都可以实现... <!DOCTYPE html> <html> <head> <meta charset=" ...

  6. Oracle数据库零散知识03

    21,存储过程,简化复杂操作,增加数据独立性,提高安全性,提高性能 与函数创建对比: create or replace function fun_01(v_01 in number) return ...

  7. System and method for dynamically adjusting to CPU performance changes

    FIELD OF THE INVENTION The present invention is related to computing systems, and more particularly ...

  8. JEECG 什么是商业版本的功能最近添加的好友?

    JEECG 商业版本号近期新增什么功能啦? 2014-12-18 JEECG JEECG jeecg添加新的功能啦! !. 1.流程设计器 2.集成工作流引擎activit,智能化封装,在线配置表单, ...

  9. Java实现多文件压缩打包的方法

    package com.biao.test; import java.io.File; import java.io.FileInputStream; import java.io.FileOutpu ...

  10. poj 3090 Visible Lattice Points 法利系列||通过计

    因为图像关于对角线对称.所以我们仅仅看下三角区域. 将x轴看做分母,被圈的点看成分子 依次是{1/2},{1/3,1/2},{1/4,3/4},{1/5,2/5,3/5,4/5} 写成前缀和的形式就是 ...