你的位置:首页 > 数据库

[数据库]使用SQLServer同义词,解决数据库复制中订阅库数据丢失几条数据订阅无法正常进行的问题


最近给客户做了基于SQLServer的发布订阅的“读写分离”功能,但是某些表数据很大,经常发生某几条数据丢失的问题,导致订阅无法继续进行。但是每次发现问题重新做一次发布订阅又非常消耗时间,所以还得根据“复制监视器”的提示,找到丢失的数据,手工处理。

网上提供的解决方案是用一个工具生成差异的SQL数据然后给订阅库执行,但看了下觉得不是很方便,想起来SqlServer还提供一个 insert...from....语句,那么是否可以直接从发布数据库查询数据然后插入给订阅数据库呢?
于是,先在订阅库上建立一个同义词,比如下面为表 Biz_Customer 建立一个同义词 Biz_Customer_Master,建立的时候,要求指定同义词所在的服务器名称,数据库名称,架构,表名称等信息。

但是此时同义词还不能直接使用,还需要建立“链接服务器”,具体过程如下:

EXEC sp_addlinkedserver @server='192.168.7.4',--被访问的服务器别名(习惯上直接使用目标服务器IP,或取个别名如:JOY) @srvproduct='', @provider='SQLOLEDB', @datasrc='192.168.7.4' --要访问的服务器 go EXEC sp_addlinkedsrvlogin '192.168.7.4', --被访问的服务器别名(如果上面sp_addlinkedserver中使用别名JOY,则这里也是JOY) 'false', NULL, 'sa', --帐号 '1234567890' --密码goselect * from sys.servers;

然后使用下面的SQL语句插入数据:

insert into [Biz_Customer] select * from Biz_Customer_Master where id='7B210173-7382-43EB-BC5E-0000C3BA564A'

查询报错,某个列的数据类型错误,打开表一看,原来是 发布库上的表的字段顺序跟订阅库上不一样,因为当初做订阅的时候,为了解决Timestamp 问题,将订阅库的Timestamp字段修改成了binary(8)类型,故订阅库上表的字段顺序改变了。

此时,只需要在insert 和 select 语句上,指定相同顺序的列就可以了。那么如何获取表所有的列名称?
很简单,直接选择某个表,新建查询,生成的SQL语句就包含表所有的字段了。
最后正确的语句如下:

insert into [Biz_Customer]([Id]   ,[CustomerId]   ,[Code]   ,[Name]   ,[BusinessId]   ,[CreatedOn]   ,[CreatedById]   ,[ModifiedOn]   ,[ModifiedById]   ,[AppraiseTableType]   ,[Timestamp]   )SELECT [Id]   ,[CustomerId]   ,[Code]   ,[Name]   ,[BusinessId]   ,[CreatedOn]   ,[CreatedById]   ,[ModifiedOn]   ,[ModifiedById]   ,[AppraiseTableType]   ,[Timestamp] FROM dbo.Biz_Customer_Master  where id='7B210173-7382-43EB-BC5E-0000C3BA564A';

经过这样的方式,很方便的把发布库的数据就补充到订阅库上了,之后,数据库的发布订阅错误就解决了。