从 SQL Server Compact 3.5 Service Pack 2 (SP2) 开始,SQL Server Compact 向其更改跟踪基础结构公开一个接口。在对 SQL Server Compact 数据库中的表启用跟踪之后,SQL Server Compact 将跟踪对表所做的更改(即插入、更新和删除)。这也称为更改跟踪。您可以使用由更改跟踪提供的数据来生成各种功能强大的应用程序。例如,可以使用更改跟踪数据来生成为偶尔连接的系统 (OCS) 提供同步服务的应用程序,在这类系统中,设备或计算机需要与服务器或网络中的其他对等方连接并同步数据。
一般而言,SQL Server Compact 通过执行以下操作实现更改跟踪:
向启用跟踪的用户表添加三个系统列。
创建三个系统表以存储跟踪特定的元数据。
在添加到所跟踪的用户表的系统列中存储跟踪元数据。
在系统表中存储跟踪元数据。
通过新类以及向 System.Data.SqlServerCe 命名空间中的现有类进行添加,向开发人员公开跟踪基础结构控制。
备注
所有以“__sys”开头的表都是系统表。这些表由 SQL Server Compact 运行时创建和维护。应用程序无法直接更改或删除系统表中的数据。SqlCeChangeTracking 类中的某些方法提供有限的功能来处理系统表。以下各部分介绍了这些方法(如果适用)。
本主题中其他各部分提供的信息可帮助您开发旨在使用更改跟踪的应用程序。
事务序列号
SQL Server Compact 使用两个编号来标识在一个表或一组表中插入、更新或删除数据的事务开始和提交所依据的顺序。
开始序列号 (BSN) 是一个单调递增的计数器,它唯一标识针对数据库开始事务的顺序。它由 SQL Server Compact 在事务开始时分配,并对于下一个要开始的事务递增。
提交序列号 (CSN) 是一个单调递增的计数器,它唯一标识针对数据库提交事务的顺序。它由数据库在事务提交时分配,并对于下一个要提交的事务递增。
BSN 和 CSN 唯一标识特定事务相对于针对 SQL Server Compact 数据库执行的其他事务开始和提交的顺序。
添加到跟踪表中的列(行内元数据)
当对用户表启用跟踪时,SQL Server Compact 向表中添加 3 列。它存储有关应用于这两列中每行的更改的元数据;第三列可选用于存储应用程序特定的上下文信息。当禁用跟踪时,将删除这些列。
下表介绍所添加的用于保留此行内元数据的列。
列名称 |
数据类型 |
说明 |
---|---|---|
__sysChangeTxBsn |
binary(8) |
用于更新行的最后一个事务的 BSN。 |
__sysInsertTxBsn |
binary(8) |
用于插入行的事务的 BSN。 |
__sysTrackingContext |
uniqueidentifier |
应用程序特定的上下文信息。根据用于修改行的最后一个事务的 (SqlCeTransaction) 的 TrackingContext 属性设置此列。开发人员可以使用此属性来保留特定于应用程序的信息。例如,标识更改数据的用户或系统。 |
对于删除,除了从表中删除行之外,SQL Server Compact 还添加了一行,其中包括有关与逻辑删除表中的已删除行相关的信息。
系统表
下面的系统表用于跟踪更改。
逻辑删除表
当从已启用跟踪的表中删除某行时,将在逻辑删除表 (__sysOCSDeletedRows) 中创建一个记录。数据库中有一个逻辑删除表,该表包含有关从数据库中的任何跟踪表中删除的行的信息。下表说明了逻辑删除表的各个列。
列名称 |
数据类型 |
说明 |
---|---|---|
__sysTN |
nvarchar(128) |
从中删除行的用户表的名称。 |
__sysDeleteTxBsn |
binary(8) |
用于删除行的事务的 BSN。 |
__sysInsertTxBsn |
binary(8) |
用于将行插入到用户表的事务的 BSN。 |
__sysRK |
varbinary(8000) |
行键。行键可以是用户表的主键或用户表中数据类型为 uniqueidentifier 且应用了 ROWGUIDCOL 属性的列(ROWGUID 列)。行键向跟踪系统唯一标识用户表行。行键以序列化格式存储在逻辑删除表中。 |
__sysDeletedTime |
datetime |
从用户表中删除行的时间。 |
当行键为单列主键或 ROWGUID 列时,它可能由用户表中的单一列组成;或者,如果主键由多个列组成,则行键可以包含多个具有不同数据类型的列。因此,行键以序列化格式存储在逻辑删除表中。可以使用 PackTombstoneKey 和 UnpackTombstoneKey 方法转入或转出此序列化格式。可以通过将 TrackingKeyType 枚举的值之一作为参数传递给 EnableTracking 方法以对表启用跟踪,对由跟踪系统使用的用户表(主键或 ROWGUID 列)设置键的类型。
随着时间推移,逻辑删除表将变得相当大。您可以使用 PurgeTombstoneTableData 方法从表中删除行。从逻辑删除表中清除行时可以采用以下两种方法:基于从用户表中删除这些行后所经过的天数(基于时间的清除),或者基于删除它们的事务的 CSN(基于 CSN 的清除)。
事务提交序列表
事务可以按与开始它们时的不同顺序提交(不按顺序提交)。提交序列表 (__sysTxCommitSequence) 跟踪这些不按顺序提交的事务。如果某个事务正在执行不按顺序的提交,则当提交该事务时,将向此表中插入一行。下表说明了事务提交序列表的各个列。
列名称 |
数据类型 |
说明 |
---|---|---|
__sysTxBsn |
binary(8) |
事务的 BSN。 |
__sysTxCsn |
binary(8) |
事务的 CSN。 |
__sysCommitTime |
datetime |
提交事务的时间。 |
备注
仅针对不按顺序提交的事务,才向事务提交序列表中添加一行。
下面的示例演示如何将事务插入到事务提交序列表中。
请考虑五个事务:T1、T2、T3、T4 和 T5。
这些事务具有以下特征:
事务开始序列(开始顺序)为 T1、T2、T3、T4、T5。
事务提交序列(提交顺序)为 T1、T3、T4、T2、T5。
假设这组事务的 CSN 和 BSN 均从 1 开始。下表介绍了每个事务的 CSN 和 BSN,以及是否应在事务提交序列表中为该事务添加一个项。
T1 |
T2 |
T3 |
T4 |
T5 |
|
---|---|---|---|---|---|
BSN |
1 |
2 |
3 |
4 |
5 |
CSN |
1 |
4 |
2 |
3 |
5 |
是否向 __sysTxCommitSequence 中插入行? |
否 |
是 |
是 |
是 |
否 |
随着时间推移,事务提交序列表的大小将变得非常大。您可以使用 PurgeTransactionSequenceData 方法从此系统表中删除行。从该表中清除行时可以采用以下两种方法:基于添加这些行后所经过的天数(基于时间的清除),或者基于事务的 CSN(基于 CSN 的清除)。
枚举对表的更改
本部分中的查询提供了有关如何枚举对表的更改的示例。对其枚举更改的表的名称在每个查询的参数 {0} 中传递。
还定义了以下参数:
EBSN:枚举开始序列号,固化的事务 BSN,就在同步开始枚举更改之前。此值用于避免获取在枚举时对表所做的任何更改。
ECSN:枚举提交序列号,固化的事务 CSN,就在同步开始枚举更改之前。此值用于避免获取在枚举时对表所做的任何更改。
LBSN:上次同步开始序列号,上一次成功同步的 EBSN。
LCSN:上次同步提交序列号,上一次成功同步的 ECSN。
备注
上载可独立于下载进行提交。在完成并确认上载后,LBSN 设置为 EBSN,而 LCSN 设置为 ECSN。
以下查询枚举插入:
private const string cmdEnumerateInserts =
" select ut.* from " +
" (select ut0.* from {0} as ut0 where " +
" ut0.__sysInsertTxBsn IS NOT NULL AND ut0.__sysChangeTxBsn IS NOT NULL AND ut0.__sysChangeTxBsn >= @LBSN " +
" ) as ut " +
" LEFT OUTER JOIN " +
" (select txcs0.* from __sysTxCommitSequence as txcs0) as txcs " +
" ON (ut.__sysInsertTxBsn = txcs.__sysTxBsn) WHERE " +
" (txcs.__sysTxBsn IS NOT NULL and txcs.__sysTxCsn >= @LCSN AND txcs.__sysTxCsn < @ECSN) OR " +
" (txcs.__sysTxBsn IS NULL AND ut.__sysInsertTxBsn >= @LCSN AND ut.__sysInsertTxBsn < @ECSN)";
以下查询枚举更新:
private const string cmdEnumerateUpdates =
" SELECT ut.* FROM " +
" (select ut0.* from {0} as ut0 where " +
" (ut0.__sysChangeTxBsn IS NOT NULL AND ut0.__sysChangeTxBsn >= @LBSN) " +
" ) as ut " +
" LEFT OUTER JOIN" +
" (select txcs0.* from __sysTxCommitSequence as txcs0) as txcs " +
" ON ut.__sysChangeTxBsn = txcs.__sysTxBsn OR txcs.__sysTxBsn IS NULL WHERE " +
" (txcs.__sysTxBsn IS NOT NULL AND txcs.__sysTxCsn >= @LCSN AND txcs.__sysTxCsn < @ECSN) OR " +
" (txcs.__sysTxBsn IS NULL AND ut.__sysChangeTxBsn >= @LCSN AND ut.__sysChangeTxBsn < @ECSN) ";
以下查询枚举删除:
private const string cmdEnumerateDeletes =
" SELECT ut.__sysRK FROM " +
" (select ut0.* from __sysOcsDeletedRows as ut0 where " +
" (ut0.__sysInsertTxCsn IS NULL OR ut0.__sysInsertTxCsn < @LCSN) and " + // Filter INSERT + DELETE
" ut0.__sysTName = \'{0}\'" +
" ) AS ut " +
" LEFT OUTER JOIN " +
" (select txcs0.* from __sysTxCommitSequence as txcs0) as txcs " +
" ON ut.__sysDeleteTxBsn = txcs.__sysTxBsn OR txcs.__sysTxBsn IS NULL WHERE " +
" (txcs.__sysTxBsn IS NOT NULL AND txcs.__sysTxCsn >= @LCSN AND txcs.__sysTxCsn < @ECSN) OR " +
" (txcs.__sysTxBsn IS NULL AND ut.__sysDeleteTxBsn >= @LCSN AND ut.__sysDeleteTxBsn < @ECSN) ";
以编程方式控制更改跟踪
您可以使用新类以及添加到 System.Data.SqlServerCe 命名空间中现有类的属性,对 SQL Server Compact 数据库配置和控制更改跟踪。下表简要概述了这些新工具。
工具 |
定义 |
---|---|
PurgeType 枚举。 |
包含的值用于指定从逻辑删除表或事务提交序列表中清除跟踪数据时是基于时间还是基于 CSN。 |
更改跟踪中使用的主要类。提供的方法用于对 SQL Server Compact 数据库中的表配置、启用和禁用更改跟踪。还提供了方法来从逻辑删除表和事务提交序列表中清除跟踪数据;以及升级 SQL Server Compact 3.5 SP2 数据库以供 Microsoft Sync Framework 1.0 SP1 和更高版本的 Sync Framework 使用。 |
|
添加了两个新属性。CurrentTransactionBsn 属性返回由 SQL Server Compact 分配给事务的 BSN。提供了 TrackingContext 属性以保留应用程序特定的信息。此信息可由开发人员定义。当修改启用跟踪的用户表时,所修改行中的 __sysTrackingContext 列设置为 TrackingContext 属性的值。 |
|
TrackingKeyType 枚举。 |
包含的值指定要用于向更改跟踪基础结构唯一标识用户表中的各行的键类型。这可以是为表定义的主键,或类型为 uniqueidentifier 且已应用了 ROWGUIDCOL 属性的列。 |
TrackingOptions 枚举。 |
包含的值指定要对用户表跟踪的操作类型。可以针对表跟踪插入、更新、删除或任何这些操作的组合。 |