SQL Server自定义业务功能的数据同步
在不同业务需求的驱动下,数据库的模块化拆分将会面临一些比较特殊的业务逻辑处理需求。例如,在数据库层面的数据同步需求。同步过程中,可能会有一些比较复杂的业务逻辑判断。简单介绍几个SQL Server提供的数据同步功能。
- 已链接服务(Linked Server)
通过链接数据库可以实现不同实例间数据的访问和更新操作。通常会与OPENQUERY行集函数一起使用,以避免分布式事务的干涉。不建议直接使用已链接服务来做远程数据的更新操作,因为这需要使用到分布式数据库的事务管理。SQL Server的分布式事务需要通过Windows的DTC(Distributed Transaction Controller,分布式事务控制器)来管理和协调不同服务器,或者说不同数据库实例间的资源和事务调整,其性能与普通的事务管理成几何倍的增长。
如图10-4,页面是已链接服务的配置界面,可以通过SSMS的Server Objects中的Linked Servers可视化页面来进行配置。
图11-4 数据库的已链接服务
Provider是已链接服务器连接数据库时使用的适配器的类型,如图11-4中,左边部分显示的,列出了几趾已有的适配器的类型。示例中,使用SQLOLEDB类型的适配器进行数据库连接。
Security页用来配置链接服务器的验证信息,它包括如图11-5中所示的4种模式的验证方式。
Not be made
当选择此认证模式时,已链接服务将使用本地服务的登陆用户与远程服务登陆用户的映射配置列表中的账号。如图中,当选择此模式时,本地将只能使用sa登陆时,模拟远程服务的sa账号的权限配置。
Without using a Security context
选择此模式将不使用验证模式,它只利用SQL Server服务的登陆账号进行验证,此服务要求在Windows服务启动时,本地服务和远程服务使用相同的登陆账号。
Using current security context
当使用此模式时,要求本地和远程服务都要有相同的账号及密码,通常这些配置为Windows集成认证的时候使用。
Using this security context
使用此模式时,将使用下面配置的用户和密码进行登陆远程服务。
本小节中只是简略地介绍了关于这些配置的简要步骤,要获取更详细的内容,请参考SQL Server联机丛书(http://technet.microsoft.com/zh-cn/library/ff772782.aspx)。
图11-5 链接服务器安全配置
- 更改跟踪(Change Tracking)
更改跟踪是SQL Server 2008加入的一个轻量级的数据修改记录功能,它是数据变更捕获功能的缩减版本。它可以将已修改数据的主键记录在对应的视图中,而后通过系统函数访问该视图,获得相应的变更数据。通过变更数据的记录,可以实现增量地处理复杂的业务逻辑,而后将数据结果保存到目标数据库中。
示例代码如代码清单11-1中所示,开启更改跟踪是依据表来配置的,但是在配置表的更改跟踪之前,需要将数据库的更改跟踪选项开启,开启数据库更改跟踪选项时,默认会将更改跟踪记录保留2天,并开启自动清理的选项。
更改跟踪可以跟踪到具体的字段更改配置,如代码清单11-1中,TRACK_COLUMNS_UPDATED配置所示,当选项为ON状态时,将会记录下更改跟踪修改的字段,当为OFF时,将不会记录。
USE master
GO
ALTER DATABASE [AdventureWorks2008R2] SET CHANGE_TRACKING = ON (CHANGE_RETENTION = 2 DAYS,AUTO_CLEANUP = ON);
GO
USE AdventureWorks2008R2
GO
ALTER TABLE Person.BusinessEntity ENABLE CHANGE_TRACKING WITH(TRACK_COLUMNS_UPDATED = ON);
GO
?
UPDATE TOP(10) Person.BusinessEntity
SET ModifiedDate=ModifiedDate;
GO
?
SELECT *
FROM CHANGETABLE(CHANGES Person.BusinessEntity,0) AS o;
GO
?
代码清单11-1 设置更改跟踪
图11-6 更改跟踪查询结果
代码清单11-1中的执行结果如图11-6中所示,使用CHANGETABLE可以获得对应表的更改历史,更改历史会将原有表的主键记录下来,如图11-6中BusinessEntityID字段所示。
关于更改跟踪的详细信息,可以参考一下SQL Server联机丛书。
- Service Broker
Service Broker是SQL Server自带的消息队列机制,通过Service Broker可以实现数据实例与实例间的通讯,同时也可以作为数据库实例与应用程序的消息传递机制。
同时,Service Broker是队列机制实现的,可以保证消息的执行顺序,对于具有事务性要求的数据同步,Service Broker将是很理想的一个数据同步实现。
如代码清单11-2中所示,配置了Service Broker在同实例下的同步配置。配置包括创建消息类型(Message Type),创建消息规则(Contract),队列(Queue)以及服务(Server)。其层级结构如图11-7中所示,首先,消息是存放在队列中的,每个队列都需要一个唯一的服务对应,服务将成为找到对应的标识。服务与服务间通讯时,需要指定相同的,相互可以识别到的消息规则,这些规则会指定对应的消息通讯的类型。其工作的流程,如图11-8中所示。
图11-7 Service Broker的组件组成
图11-8 Service Broker的工作原理
当需要进行队列传输前,需要开启一个会话(Conversation),通过会话记录下对应的服务标识,标识从源服务发送到目标服务。找到会话标识后便可以找到对应的队列。
开启会话以后,进行消息发送,对于数据库实例来说,只需要将消息写入到发送队列就可以了。消息被写入到发送队列后,后续的工作都交给Service Broker来处理。
当消息进入发送队列,Service Broker根据会话记录的服务标识,找到目标服务,并将消息拆分为多个消息片断,将消息发送到目标服务,服务接收完成所有的消息后,将消息写入到目标队列中。在写入到目标队列后,消息传递就结束了。后续的工作便交给应用处理了。
应用需要调用接收消息的命令,将消息从接收队列中取出,并进行一系列的后续业务工作。
关于Service Broker可以参考SQL Server联机丛书(http://technet.microsoft.com/zh-cn/library/ms166104(v=SQL.105).aspx)。
下面的代码是一份在同一实例下进行Service Broker配置以及测试的脚本,可以参考一下代码,并结合上图11-8中的工作原理参考Service Broker的工作方式。
use master
go
alter database AdventureWorks2008R2 set enable_broker with rollback immediate;
go
?
use AdventureWorks2008R2
go
?
create message type ReceiveMsgType validation = none;
create message type SendMsgType validation = none;
?
go
create contract SampleContract(SendMsgType sent by initiator,ReceiveMsgType sent by target,FraudEndOfStream sent by initiator);
go
?
create queue SampleTargetQue;
create service SampleTargetSrv on queue SampleTargetQue(SampleContract);
go
?
create queue SampleInitQue;
create service SampleInitSrv on queue SampleInitQue(SampleContract);
go
?
/********************************Send Test********************************************
declare @handle uniqueidentifier,@msg varchar(8000) = ‘this is a test message!‘;
?
begin dialog conversation @handle
from service SampleInitSrv
to service ‘SampleTargetSrv‘
on contract SampleContract
with encryption = off;
?
send on conversation @handle
message type SendMsgType(@msg)
?
**********************************************************************************/
?
/*****************************Receive Test*************************************************
declare @receivemsg varchar(8000),@Handle uniqueidentifier;
waitfor(receive top(1) @Handle = conversation_handle,
[email protected] = Message_Body
????????????from SampleTargetQue),timeout 1000
end conversation @handle;
select @receivemsg;
?
**********************************************************************************/
代码清单11-2 同实例下的Service Broker配置