我的组织最近遇到了一些SQL Server阻止进程的问题。 dbWarden已成功向我们报告阻止,但我们经常将阻塞的SQL文本报告为“FETCH API_CURSOR”。 因此,我们希望在dbWarden中更改阻塞警报触发器,以便在我们发现“FETCH API_CURSOR”报告的情况下使用sys.dm_exec_cursors和sys.dm_exec_sql_text检索文本。
麻烦的是,我似乎无法想出一种在我们的开发服务器上重新创建/模拟阻塞情况的方法,该服务器将报告为'FETCH API_CURSOR'。我已经从VB脚本here on SQL Authority开始重新创建打开的光标,但是我不能为我的生活弄清楚如何阻止它。
我见过很多重新创建阻塞事务的方法(在一个窗口中打开一个事务,但是不提交/关闭,然后在另一个窗口中尝试对同一个表进行更新),但不会以某种方式利用FETCH API_CURSOR会让我们成功测试。我在这里有些不知所措。
过去有没有人成功模拟阻塞游标并可以提供建议?
答案 0 :(得分:0)
我建议您使用Profiler工具捕获创建和获取光标的实际代码。在这种情况下,您可以准确地看到应用程序中发生了什么。在开发服务器上重现类似的阻塞并不困难。
假设一个线程从游标中获取行,另一个线程尝试更新相同的行。看看幕后发生了什么。读取线程创建游标以将SELECT的结果提取回应用程序。这项技术很古老而且非常慢,现在只有一些旧的(大多数)Java应用程序使用游标来达到这个目的。行逐个获取,客户端正在处理此过程,因此需要时间。在此期间,读取线程会对其读取的数据保持共享锁定。它是设计使然,SQL Server是更衣室,它确实使用锁来正常运行。如果另一个线程尝试更新已使用共享锁锁定的行,则会被阻止。因为更新线程在搜索行进行更新时使用共享锁,并尝试将其升级为更严重的行,但不能。例如,如果另一个线程在同一行拥有S锁,则无法将共享锁升级为U锁。所以我尝试创建一个游标,获取几行并尝试在另一个选项卡中更新。如果您发现困难,请尝试增加阅读事务序列化级别。
但是,严肃地说,我认为你不必在开发服务器上重现这个或类似的场景。停止使用游标进行记录集获取!读取速度会快得多,阻塞问题也会大大减少。自从1989年游戏看到了他们的伟大时代以来已经有一段时间了。客户端数据库访问库发展很多,值得尝试取得进步的成果。即使在Java中,它也是一个配置选项,使用或不使用它们。
我很抱歉在这种情况下游标是否会被故意使用。这是非常不可能的,但可能。我好久没见过这种“正确”的光标使用了!我很高兴再遇到一个合适的案例。