SQL MIN_ACTIVE_ROWVERSION() 值长时间不变
Posted
技术标签:
【中文标题】SQL MIN_ACTIVE_ROWVERSION() 值长时间不变【英文标题】:SQL MIN_ACTIVE_ROWVERSION() value does not change for a long while 【发布时间】:2013-02-28 18:46:47 【问题描述】:我们正在通过链接服务器连接对两个 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
的值。
我们最初认为这与尚未提交的待处理数据库事务有关。根据 MSDN 关于MIN_ACTIVE_ROWVERSION()
(link) 的定义:
返回当前数据库中最低的活动 rowversion 值。如果在尚未提交的事务中使用 rowversion 值,则它是活动的。
但是在此问题期间检查与 open_tran > 0
的会话 (sys.sysprocesses
) 时,我们找不到任何 waittime 大于几秒钟,只有一两次 +/- 5 分钟的 waittime 会话。
所以在这一点上,我们正在努力了解情况:MIN_ACTIVE_ROWVERSION()
在很长一段时间内不会发生变化,并且在此时间范围内没有发现长时间等待的未提交事务。
我不是 DBA,可能是我们在图片中遗漏了一些东西来分析这个问题,在论坛和博客上做一些研究找不到任何其他线索。到目前为止 open_tran > 0 是正当的原因,但在我暴露的情况下,很明显还有别的东西,不知道为什么。
感谢任何反馈。
【问题讨论】:
+1 对于这样一个写得很好的问题。与其将您的解决方案添加到您的问题中,不如将其添加为答案。 @luiggig:解决方案——即使是你自己——也应该作为答案发布。随意发布该部分作为答案。然后接受它,如果没有其他人想出更好的。 【参考方案1】:好吧,我在挖掘更多之后终于找到了解决方案。
问题在于我们正在寻找具有较长等待时间 的会话,但真正的问题是找到一段时间以来具有活动批次 的会话。
如果有一个会话,其中 open_tran = 1,要准确获取此事务何时打开(当然仍然处于活动状态,尚未提交),则应检查来自 sys.sysprocesses
的字段 last_batch。
使用这个查询:
select
batchDurationMin= DATEDIFF(second,last_batch,getutcdate())/60.0,
batchDurationSecs= DATEDIFF(second,last_batch,getutcdate()),
hostname,open_tran,* from sys.sysprocesses a
where spid > 50
and a.open_tran >0
order by last_batch asc
我们可以识别一个开放式传输超过 30 分钟的会话。通过主机名值和 Web 服务中的更多检查(也使用dbcc inputbuffer
),我们找到了负责的进程。
所以,最后一个问题实际上是“确实存在一个未提交事务的活动会话”,因此MIN_ACTIVE_ROWVERSION()
不会改变。我们只是在寻找具有错误标准的流程。
现在我们已经知道哪个流程的行为是这样的,下一步将是改进它。
希望这个结果对其他人有用。
【讨论】:
我已经确认了这一点:MIN_ACTIVE_ROWVERSION() 直到在该版本开始的第一个事务完成后才会增加。以上是关于SQL MIN_ACTIVE_ROWVERSION() 值长时间不变的主要内容,如果未能解决你的问题,请参考以下文章