Jez*_*Jez 9 sql-server sql-server-2008-r2
我注意到当您设置事务复制时,SQL Server 会将标识范围管理设置为手动。这意味着在我的订阅数据库中,当我尝试将一条新记录插入到 PK 是标识列的表中时,它会给我一个错误并说它试图插入一个“1”、“2”的 PK "、"3" 等。这是因为订阅者上所有标识列的当前标识值被重置为种子值(通常为 1),而不是保持在发布者上的值。
我理解 SQL Server 这样做的原因 - 您应该将订阅者表保留为只读。但是,我的场景有点不正统 - 我通过复制不时更新我的订阅者,立即备份该数据库,然后我想对订阅者进行一些不会被推回发布者的更新,然后当我再次更新订阅者时,我从较早的备份中恢复其数据库并提取最新更新。因为我想在这些更新之间对订阅者进行更新('临时增量',如果你愿意的话),我需要标识列工作,而不是在复制时重置为 1。
我在设置发布时尝试打开自动标识范围管理,但是当我尝试将表添加到发布时,这只会给我以下错误:
消息 21231,级别 16,状态 1,过程 sp_MSrepl_addarticle,第 2243 行
自动标识范围支持仅对允许更新订阅者的发布有用。
有什么办法可以解决这个问题吗?我确实想将此复制呈现给 SQL Server,就好像它在订阅者端是只读的一样,因为我不打算进行将推送回发布者的更新,但我确实想要进行临时更新将在下一次复制之前被擦除。
我还考虑过快照复制可能是比事务复制更适合我的使用模式的方法,但问题是快照复制需要每次更新都发送整个该死的数据库;因为我打算在最近一次复制后立即备份数据库,所以我不需要每次都进行整个传输;只是自上次以来的变化。
我最终做的是坚持使用基于拉的事务复制,并让我的程序在同步后立即将订户身份值更新为与发布数据库上的值相同(有点像我希望分发代理自行执行的操作) )。在伪代码中,它看起来有点像这样:
synchronize databases with TransSynchronizationAgent
equivalentTablesNotFound is a list of strings
for each table in publisher tables:
try:
check table identity value (this is via functionality provided by .NET's Microsoft.SqlServer.Management.Smo.Server class)
parse identity value as integer to newIdentity
if the table's identity value was NULL, skip to next loop iteration
(HACK) increment newIdentity value by 1
if there is no subscriber table with the same name as this one:
record its name in equivalentTablesNotFound and skip to next loop iteration
set subscriber table with same name's identity value to newIdentity using TSQL: DBCC CHECKIDENT ("tableName", newIdentity)
catch:
if exception shows that the error was because the table doesn't have an identity column, drop the exception
if equivalentTablesNotFound has more than zero entries, warn about tables on publisher without an equivalent name on subscriber
Run Code Online (Sandbox Code Playgroud)
似乎工作正常。HACK 位是因为,尽管默认情况下以及我的所有表中,标识值仅递增 1,但它可以进行不同的配置,因此从技术上讲,您应该了解发布者表上的标识值如何递增,并将其递增同样的方式。