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 &gt; 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() 值长时间不变的主要内容,如果未能解决你的问题,请参考以下文章

sql 2008和sql 2012的区别

sql [sql技巧]一些sql技巧#sql

sql 2008 r2 在sql 2008上兼容么

SQL基础

有大神知道,sql server 中如何批量执行sql语句吗?

pl sql developer怎么执行sql