none
SQL Server的复制设置中已经禁用复制外键约束,但一段时间后在订阅数据库表上还是看到外键约束,这算Bug吗? RRS feed

  • 问题

  • 上两张图就能说明问题:

    红框中的FK开头的外键为何会出现在订阅数据库表中?第一张图显示,发布的那张表示明明取消了复制外键约束的。还有一个问题是复制过来的外键名字也丢失了,变成FK开头的一串16进制字符串。

    这种情况在复制运行几天后就会出现,如果在订阅数据库中强制删除这些外键,等再过几天又从发布数据库同步过来了。

    这算是Bug吗?

    2014年2月26日 16:31

全部回复

  • That option means don't copy fkeys to subscriber in snapshot, but sql replicates schema changes by default. Did you specify 'not for replication' in fkeys on publisher by the way?
    2014年2月26日 17:09
  • I understand. There is indeed a 'forced to be used in replication' option in fkeys settings.
    2014年2月28日 1:54
  • 正如rmiao大侠所说,这个选项仅针对快照集。

    默认情况下,创建好replication,并且添加了subscriber之后,默认会同步constraint。 但是不会默认同步index


    If you haven't all the things you want,be grateful for the things you don't have that you didn't want.

    2014年2月28日 7:52
  • 我查看了下,我发现外键设置中“强制用于复制”选项已经选否的外键还是会被同步过去。

    请问还要在发布数据库里修改什么设置才能阻止外键被复制过去?

    能举个例子吗?

    2014年2月28日 15:44
  • Option 'not for replication' mean sql will not force fkey on subscriber, doesn't mean not replicate fkeys.
    2014年2月28日 16:55
  • 你的意思是外键约束复制到订阅数据库中,但不会强制生效吗?是这个意思吗?怎么可能,实际上复制偶尔会中断,几乎都是外键冲突导致的,我用一个存储过程删除库里的所有表外键,然后复制很快就会自动恢复正常状态。

    然后没过多久删除的外键约束又会自动产生,然后再过一段时间就会又出现按外键冲突。

    请问您你能解释这种现象吗?您有解决方案吗?

    2014年3月1日 14:33
  • That's way you have to use 'not for replication' when create fkey in replicated table.

    2014年3月2日 0:15
  • 很感谢rmiao的多次回复。但是我不得不取消答案标记。因为他所说的'not for replication' 设置我不知道指的是什么。我已经把我所知道的几个地方都试过了。
    2014年3月7日 10:20
  • Take look at 'Controlling Constraints, Identities, and Triggers with NOT FOR REPLICATION' in books online.

    2014年3月7日 14:00
  • rmiao大侠的意思是在在发布表中创建外键约束时指定“not for replication

    chenl

    2014年3月11日 0:58
  • 这个问题是2年前问的,但是没有解决问题。几个回复的答案都没法说明该如何操作。几年了一直被这个问题困扰着。请问还有人能给个明确答案说明如何阻止订阅数据库表上出现外键吗?发布表中创建外键约束时指定“not for replication”,请问您说的这个操作是如何操作?您能说明确吗?

    我是真想提Bug了。不过提了Bug估计也没用。我还有个IE Javascript CROS的Bug也挂了几年了,也没个说法。

    微软有人能看到吗?


    2016年2月16日 9:40
  • You can specify 'not for replication' when create fkey, books online has detailed syntax under 'ALTER TABLE (Transact-SQL)'.
    2016年2月16日 17:57
  • 外键属于 DDL ,这个操作默认会应用在订阅上,但名称会与发布一样(就算自动生成名称,在订阅上应用的DDL,也是把名称弄过去的)

    如果名称不一样,那么你建个 DDL 触发器跟踪一下,确定是否来自于发布

    另外,你的 SQL版本是什么?

    2016年2月17日 2:08
  • NOT FOR REPLICATION选项作用于订阅服务器,如果你的外键约束是直接在订阅服务器上的,则需要确保有这个选项,类似于

    ALTER TABLE xx ADD FOREIGN KEY( fk_column ) REFERENCES fk_tb ( key_column ) NOT FOR REPLICATION

    如果你的外键约束是在发布服务器上的,那么分几种情况:

    1. 如果约束是在配置同步前建的

    1-1 如果建同步时指定不复制外键约束,那么外键约束不会复制过去,不会有问题

    1-2 如果复制外键约束,那么需要确保外键是能 NOT FOR REPLICATION选项创建的,否则会有问题

    2. 如果外键是配置同步后之后创建的

    2-1 如果建外键约束有指定 NOT FOR REPLICATION选项,那么没有问题

    2-2 如果没有指定 NOT FOR REPLICATION选项

    2-2-1 如果发布项目的 @schema_option 选项有指定 0x20000,那么没有问题

    2-2-2 如果未指定,则应该会有问题

    @schema_option  为 sp_addarticle 和 sp_changearticle 的参数,0x20000 这个值在界面中我没有看到有对应的配置项,应该只能用脚本来操作了 ( 已经配置的同步的该值可以在对应的发布数据库中查询 sysarticles 表)

    2016年2月17日 6:30
  • 邹建,rmiao:

    谢谢回复。我截图你们看下是什么情况。这是发布数据库的表的外键情况。强制用于复制是选“否”的。

    下图是订阅数据库对应表的外键的情况:

    这里出现了16进制编码名称的外键名,对应的还是第一张图里面的外键。就是这里的外键容易在复制同步时出现问题,因为外键约束导致数据删除出现问题,进而导致同步不能继续。如果把订阅数据库的表的所有外键都删除,就正常了。

    可以用存储过程把订阅数据库的所有外键都删除,但是一段时间后,这些16进制编码名称的外键又会出现,这是怎么回事呢?

    发布数据库是2008R2版本(10.50.1600.1),订阅数据库是2005版本(9.00.1399)。订阅数据库有多个,其中也有2008的版本。

    邹建所说的“外键约束”,你说的就是“键”分支中的FK开头的外键吗?因为微软SQLServer管理器“键”分支下面还有个“约束”分支,里面的项目跟外键其实没关系(我怕概念理解上有歧义)。

    我的表的这些外键,是在创建复制之前就建好的,建外键时,我没有看到你和rmiao所说的“NOT FOR REPLICATION”选项,只有“强制用于复制”选项,而且如你所见,这个是选否的。

    创建复制的属性我也截图下:

    好了,我只找到这些地方可以控制外键复制的问题,我设置有什么问题吗?该怎么办?

    2016年2月20日 13:17
  • Should set 'not for replication' on both publisher and subscriber, this option is in t-sql statement.
    2016年2月20日 16:58
  • 你的意思明确的说,就是GUI界面上是没有这个操作选项的,只能在发布和订阅数据库两边同时运行Alter table ... not for replication这个SQL才行,对不对?

    要想想多个订阅数据库,以及数据库里几十上百的表,每个订阅库的每个表都要这样操作,这个工作量多大,还要写存储过做这个事情吗?

    不这样操作就会导致同步在运行一段时间后几乎是必然的会失败。请问这还不算Bug吗?

    2016年2月21日 7:00
  • You should only do that when create tables which will be replicated.
    2016年2月21日 17:47
  • 你的意思明确的说,就是GUI界面上是没有这个操作选项的,只能在发布和订阅数据库两边同时运行Alter table ... not for replication这个SQL才行,对不对?

    要想想多个订阅数据库,以及数据库里几十上百的表,每个订阅库的每个表都要这样操作,这个工作量多大,还要写存储过做这个事情吗?

    不这样操作就会导致同步在运行一段时间后几乎是必然的会失败。请问这还不算Bug吗?

    简化一下我前面说的,具体的你再仔细看下:

    如果设置 schema option, 那么不需要alter table not for replication,这个在编写订阅外键约束的时候会自动加上,但这个选项界面上是没有的,需要通过 sp_addarticle 或 sp_changearticle 设置(也就是用脚本的方式添加或者个性发布项目)

    如果你不用脚本的方式,那么在配置发布的时候,可以选择不复制外键,但在配置好发布之后所添加的外键,需要确保有使用 not for replication 选项

    2016年2月22日 1:18
  • 复制项目属性里面的复制外键,只用于快照,也就是初始化订阅,对于后期加的外键,是不受这个影响的,受影响的是 schema option的另一个值,界面上是没有的

    你戴图里面,发布和订阅的外键约束名称是不一样的,所以应该不是 replication 同步过去的,replicaton同步过去是要保证名称一样的,这个已经建议你用 DDL 触发器跟踪了

    不要老是纠结在同步上,从你的载图看,造成问题的不是复制,应该是别的东东直接在订阅上建外键了

    2016年2月22日 1:22
  • 另外,默认好像 0x20000 是打开的,你可以在发布服务器的发布数据库中查下,如果第一列值不是0,那么证明选项是打开的,编写订阅外键约束的时候,会自动使用 not for replication 选项

    select cast(cast(schema_option as bigint) & 0x20000 as varbinary(8)), * from sysarticles

    2016年2月22日 1:28
  • 外键依赖于非聚集索引
    2016年2月25日 2:56
  • 不可能是别的东西,你说还能有什么东西?这个外键除了数据库自己(包括数据库自己的Agent等那一票东西),是没有东西能建的。应用程序是绝不可能的。只要不是同步,就不会有那些16进制的外键名称出现。

    问题是这个情况要重建一个环境稳定重现问题,也是非常麻烦的。因为这是在运营状态下才会出现的故障。

    2016年3月7日 1:11
  • 不可能是别的东西,你说还能有什么东西?这个外键除了数据库自己(包括数据库自己的Agent等那一票东西),是没有东西能建的。应用程序是绝不可能的。只要不是同步,就不会有那些16进制的外键名称出现。

    问题是这个情况要重建一个环境稳定重现问题,也是非常麻烦的。因为这是在运营状态下才会出现的故障。

    建个DDL触发器来跟踪一下很麻烦么?想这么多还不如动动手
    2016年3月7日 3:07