我们正在通过链接服务器连接对两个 SQL Server 数据库、不同服务器(均为 SQL Server 2008 Enterprise 64 位 SP2 - 10.0.4000.0)中的一种同步框架进行故障排除,我们达到了排序的点卡住了。
识别哪些是“待同步”记录的逻辑当然是基于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
该方法工作得很好,我们通常以 600k/小时的预期速率同步记录(作业每 30 秒,批量大小 = 5k),但在某些时候,同步过程找不到任何要传输的单条记录,即使有几千条记录的ROWVERSION
值大于@LastStamp
参数。
在检查原因时,我们发现MIN_ACTIVE_ROWVERSION()
的值小于(或略大于,仅 5 或 10 个增量)@LastStamp
正在搜索的值。这当然不应该是一个问题,因为MIN_ACTIVE_ROWVERSION()
引入该方法是为了避免脏读和后期问题,但是:
我们在某些情况下看到的问题,在上述场景发生期间,是MIN_ACTIVE_ROWVERSION()
在很长(非常长)的时间段内,例如 30/40 分钟,有时超过一小时,的值不会改变。而这个价值远远低于@@DBTS
价值。
我们首先认为这与尚未提交的待处理数据库事务有关。根据关于MIN_ACTIVE_ROWVERSION()
(链接)的 MSDN 定义:
返回当前数据库中的最低活动 rowversion 值。如果在尚未提交的事务中使用 rowversion 值,则它是活动的。
但是在此问题期间检查会话 ( sys.sysprocesses
)open_tran > 0
时,我们找不到任何等待时间大于几秒的会话,只有一两次出现 +/- 5 分钟的等待时间会话。
所以在这一点上,我们正在努力理解这种情况:MIN_ACTIVE_ROWVERSION()
在很长一段时间内没有变化,并且在这个时间范围内没有发现长时间等待的未提交事务。
我不是 DBA,可能是我们在图片中遗漏了一些东西来分析这个问题,在论坛和博客上做一些研究找不到任何其他线索。到目前为止, open_tran > 0 是正当的原因,但在我暴露的情况下,很明显还有别的东西,不知道为什么。
任何反馈表示赞赏。