码迷,mamicode.com
首页 > 其他好文 > 详细

Transaction Replication1:Subscription PK columns are readonly

时间:2015-12-16 15:34:09      阅读:180      评论:0      收藏:0      [点我收藏+]

标签:

在使用Transaction Replication时,Subscriber 端必须是Read Only的 , all data at the Subscriber is “read-only” (transactional replication does not enforce this at the Subscriber),不能更新Subscriber端的数据的主键,否则,某些数据更新操作会失败。

 

在Transaction Replication中,How Changes Are Propagated for Transactional Articles?

默认的是使用系统自动生成的存储过程来更新(delete,update,insert)数据的。

transactional replication should script out and subsequently call a stored procedure to propagate changes to Subscribers (the default).

By default, transactional replication propagates changes to Subscribers through a set of stored procedures that are installed on each Subscriber. When an insert, update or delete occurs on a table at the Publisher, the operation is translated into a call to a stored procedure at the Subscriber. The stored procedure accepts parameters that map to the columns in the table, allowing those columns to be changed at the Subscriber.

 

Default stored procedures

The three procedures that replication creates by default for each table article are:

  • sp_MSins_< tablename >, which handles inserts.

  • sp_MSupd_< tablename >, which handles updates.

  • sp_MSdel_< tablename >, which handles deletes.

The <tablename> used in the procedure depends on how the article was added to the publication and whether the subscription database contains a table of the same name with a different owner.

例如,在Programmability catalog下,有三个sp,分别是:dbo.sp_MSdel_dbodt_study,dbo.sp_MSins_dbodt_study,dbo.sp_MSupd_dbodt_study,用以对subscriber端的 dbo.dt_sutdy进行delete,insert和update 操作,这三个sp每次执行时必须保证update,insert或update的数据行数是1如果更新的记录数量不是1,那么报错。用于Publication的Table必须有PK,PK起到唯一标识一条记录的作用。

技术分享

1,查看 dbo.sp_MSdel_dbodt_study 的源代码

ALTER procedure [dbo].[sp_MSdel_dbodt_study]
        @pkc1 int
as
begin  
    delete [dbo].[dt_study]
    where [id] = @pkc1
if @@rowcount = 0
    if @@microsoftversion>0x07320000
        exec sp_MSreplraiserror 20598
end 


delete data command 使用 PK column作为Delete的Filter condition,保证删除一条记录,如果删除的数据行数为0,则报错。

 

if @@rowcount = 0 
  if  @@microsoftversion>0x07320000 
    exec sp_MSreplraiserror 20598 

These  commands ensure that if there is no matching record then error 20598 must be raised. "if @@microsoftversion>0x07320000" verifies that you are using a version of SQL Server above SQL 7.

 

2,示例分析,在Publisher端有如下数据

技术分享

如果在Publisher端使用如下脚本,删除所有的4个记录

delete dbo.dt_study_publication


那么在Subscriber端,等价的操作是在一个transaction中调用4次dbo.sp_MSdel_dbodt_study

set XACT_ABORT on

begin tran
    exec dbo.sp_MSdel_dbodt_study @pkc1=1
    exec dbo.sp_MSdel_dbodt_study @pkc1=2
    exec dbo.sp_MSdel_dbodt_study @pkc1=3
    exec dbo.sp_MSdel_dbodt_study @pkc1=4
commit
set XACT_ABORT off

 

如果在Subscriber端,数据有丢失,比如,PKColumn=4 的Record不存在,那么则会导致整个transactino失败,导致数据同步失败。

 

3,查看dbo.sp_MSins_dbodt_study的源代码

ALTER procedure [dbo].[sp_MSupd_dbodt_study]
        @c1 int = NULL,
        @c2 nvarchar(50) = NULL,
        @c3 bit = NULL,
        @pkc1 int = NULL,
        @bitmap binary(1)
as
begin  
if (substring(@bitmap,1,1) & 1 = 1)
begin 

update [dbo].[dt_study] set
        [id] = case substring(@bitmap,1,1) & 1 when 1 then @c1 else [id] end,
        [name] = case substring(@bitmap,1,1) & 2 when 2 then @c2 else [name] end,
        [sex] = case substring(@bitmap,1,1) & 4 when 4 then @c3 else [sex] end
    where [id] = @pkc1
if @@rowcount = 0
    if @@microsoftversion>0x07320000
        exec sp_MSreplraiserror 20598
end  
else
begin 

update [dbo].[dt_study] set
        [name] = case substring(@bitmap,1,1) & 2 when 2 then @c2 else [name] end,
        [sex] = case substring(@bitmap,1,1) & 4 when 4 then @c3 else [sex] end
    where [id] = @pkc1
if @@rowcount = 0
    if @@microsoftversion>0x07320000
        exec sp_MSreplraiserror 20598
end 
end 

update data command 使用 PK column作为update的Filter condition,保证更新一条记录,如果更新的数据行数为0,则报错。

 

4, 查看 [dbo].[sp_MSins_dbodt_study] 的源代码

ALTER procedure [dbo].[sp_MSins_dbodt_study]
    @c1 int,
    @c2 nvarchar(50),
    @c3 bit
as
begin  
    insert into [dbo].[dt_study](
        [id],
        [name],
        [sex]
    ) values (
    @c1,
    @c2,
    @c3    ) 
end  

将表数据插入到表中,在Insert子句中必须显式指定table的所有column name,在Values子句中必须显式为table的所有column赋值。如果插入成功,肯定是插入一条record;如果插入失败,Insert command会报错。

 

5,更新Subscriber端数据的非主键属性

5.1 查看Publisher和Subscriber data snapshot

Publisher Data Snapshot

技术分享

subscriber Data Snapshot

技术分享

5.2 在Publisher 端insert数据

insert into dbo.dt_study
(
ID,
name,
sex
)
values(5,abc,0)

在Subscriber端查看数据更新
技术分享

5.3 在Publisher 端更新数据

update dbo.dt_study 
set name=update5
where id=5

在Subscriber端查看数据更新

技术分享

在Subscriber端update数据

update dbo.dt_study 
set name=update6
where id=5

在Publisher 端更新数据

update dbo.dt_study 
set name=update7
where id=5

在Subscriber端查看数据更新

技术分享

可以看出,如果在Subscriber端对数据的非主键属性进行更新,那么不影响transaction replication同步数据。

 

6,更新Subscriber端数据的主键属性

在Subscriber端删除ID=5的记录

delete dbo.dt_study
where id=5

在Publisher 端 删除 dbo.dt_study 中ID>=5的所有记录

delete dbo.dt_study
where id>=5

subscriber Data Snapshot如下,subscriber数据不会更新,数据同步失败。

技术分享

 

查看 Replication Monitor,

The row was not found at the Subscriber when applying the replicated command. (Source: MSSQLServer, Error number: 20598)
Get help: http://help/20598

技术分享

 

WorkAround:在Subscriber 端中将 缺失的Row PK 补上即可。

insert into dbo.dt_study
(ID,name,sex)
values(5,null,null)

Transaction执行失败,并不会从Distribution database中移除,Distributor Agent 会多次重新执行失败的Transaction。

 

Transaction 何时从Distribution database中移除?

Transaction commands are stored in the distribution database until they are propagated to all Subscribers or until the maximum distribution retention period has been reached. Subscribers receive transactions in the same order in which they were applied at the Publisher.

Transaction Replication1:Subscription PK columns are readonly

标签:

原文地址:http://www.cnblogs.com/ljhdo/p/5050979.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!