我们正在通过链接的服务器连接在两个SQL Server数据库之间,在单独的服务器(SQL Server 2008 Enterprise 64位SP2 - 10.0.4000.0)中对一种Sync Framework进行故障排除,并且我们达到了排序的程度卡住了.
识别哪些是"待同步"的记录的逻辑当然基于ROWVERSION值,包括使用MIN_ACTIVE_ROWVERSION()以避免脏读.
所有SELECT操作都封装在每个"源"端的SP中.这是一个SP的示意图:
PROCEDURE LoaderRetrieve(@LastStamp bigint, @Rows int)
BEGIN
...
(vars handling)
...
SET TRANSACTION ISOLATION LEVEL SNAPSHOT
Select TOP (@Rows) Field1, Field2, Field3
FROM Table
WHERE [RowVersion] > @LastStampAsRowVersionDataType
AND [RowVersion] < @MinActiveVersion
Order by [RowVersion]
END
Run Code Online (Sandbox Code Playgroud)
该方法工作正常,我们通常以预期的600k /小时速率同步记录(每30秒一次作业,批量大小= 5k),但在某些时候,同步过程找不到任何单个记录要传输,即使有数千条记录的ROWVERSION值大于@LastStamp参数.
在检查原因时,我们发现搜索MIN_ACTIVE_ROWVERSION()的值小于(或稍微大一些,只有5或10个增量)@LastStamp.这当然应该不是问题,因为MIN_ACTIVE_ROWVERSION()引入该方法是为了避免脏读和后验问题,但是:
在上述情况发生期间,我们在某些情况下看到的问题是,MIN_ACTIVE_ROWVERSION()在很长(很长)的时间段内,例如30/40分钟,有时超过一小时,价值不会发生变化.而这个值远远低于该@@DBTS值.
我们首先认为这与尚未提交的待处理数据库事务有关.根据MSDN关于MIN_ACTIVE_ROWVERSION()(链接)的定义:
返回当前数据库中最低的活动rowversion值.如果在尚未提交的事务中使用rowversion值,则该rowversion值处于活动状态. …