我注意到,当您设置事务复制时,SQL Server 会将身份范围管理设置为手动。这意味着在我的订阅数据库中,当我尝试将新记录插入其 PK 是标识列的表中时,它会给我一个错误并说它试图插入一个 PK 为“1”、“2 "、"3" 等。这是因为订阅者上所有身份列的当前身份值都被重置为种子值(通常为 1),而不是保持在发布者上的值。
我理解 SQL Server 这样做的原因——您应该将订阅者表保留为只读。但是,我的情况有点不正统 - 我不时通过复制更新我的订阅者,立即备份该数据库,然后我想对订阅者进行一些不会被推回发布者的更新,然后当我再次更新订阅者时,我从早期的备份中恢复其数据库并提取最新更新。因为我想在这些更新之间对订阅者进行更新(“临时增量”,如果你愿意的话),我需要标识列正常工作,而不是在复制时重置为 1。
我在设置我的出版物时尝试打开自动身份范围管理,但是当我尝试向出版物添加表时,这只会给我以下错误:
消息 21231,级别 16,状态 1,过程 sp_MSrepl_addarticle,第 2243 行
自动标识范围支持仅对允许更新订阅者的发布有用。
有什么办法可以解决这个问题吗?我确实希望将此复制呈现给 SQL Server,就好像它在订阅者端是只读的一样,因为我不打算进行将推送回发布者的更新,但我确实想做临时更新将在下一次复制之前被删除。
对于我的使用模式,我还认为快照复制可能比事务复制更合适,但问题是快照复制需要在每次更新时发送整个该死的数据库;因为我计划在最近一次复制后立即备份数据库,所以我不需要每次都进行整个传输;只是自上次以来的变化。
假设您的发布者使用从 1 开始的 int 标识,您可以
DBCC CHECKIDENT('dbo.mytable', RESEED, -2147483648)
在订阅者处发布。然后,您可以使用从 -2147483648 到 0 的范围来保存“临时增量”。我最终做的是坚持基于拉的事务复制,并让我的程序在同步后立即更新订阅者身份值,使其与发布数据库上的值相同(我希望分发代理自行执行)。在伪代码中,它看起来有点像这样:
似乎工作正常。HACK 位是因为,虽然在默认情况下和我所有的表中,标识值只是递增 1,但它可以进行不同的配置,所以从技术上讲,您应该在这里找出标识值如何在发布者表上递增并将其递增同样的方法。
我首选的处理方法是执行以下操作:
一个。首先停止您的复制代理(这样您就不会将任何新数据输入您的订阅数据库)
湾。第二次重命名您现有的表
C。使用 IDENTITY 集重新创建表
d。使用 SET IDENTITY_INSERT 回填表(来自 [BackupTableName])
一旦你的数据库上有IDENTITY约束,那么你可以进行自定义复制(即:将你的 insert repl proc 更改为 SET IDENTITY_INSERT [TableName] ON 或者你可以在表上设置 NOT FOR REPLICATION 标志(它告诉 SQL 服务器如果连接用户是复制代理,则期望提供 IDENTITY 值)(我更喜欢自定义复制方法,因为它给了我更多的灵活性)
e. 修改您的插入复制存储过程(通常名为 sp_MSins_CurrentTable)以也使用插入
SET IDENTITY INSERT
F。现在您可以重新启动复制代理。