【发布时间】:2022-11-07 19:46:00
【问题描述】:
我正在编写的数据库工具通过对sys.dm_exec_requests 运行并行查询来调查阻塞的查询,如果主查询被延迟以找到延迟的原因。
如果调查连接具有VIEW SERVER STATE 权限,则可以正常工作。但是,如果不是,sys.dm_exec_requests 只包含它运行的连接的条目——这对于一次只能运行一个查询的连接来说有点毫无意义。
进入 MARS,我第一次想到这个神秘的功能可能对某些东西有用。
启用 MARS 后,我可以在与我们正在调查的延迟查询相同的连接上运行调查查询。
但是,一个简单的测试表明,如果第一个 MARS 查询被阻止,显然第二个也是,即使第二个没有理由。
我在 LinqPad 中运行此测试代码(使用 Dappper 以获得更紧凑的代码示例,但我在不使用 Dapper 的应用程序中得到了相同的效果):
var csb = new SqlConnectionStringBuilder();
csb.TrustServerCertificate = true;
csb.DataSource = @".\";
csb.InitialCatalog = "...";
csb.IntegratedSecurity = true;
using var c0 = new SqlConnection(csb.ConnectionString);
csb.MultipleActiveResultSets = true;
using var c1 = new SqlConnection(csb.ConnectionString);
using var c2 = new SqlConnection(csb.ConnectionString);
// Begin the blocking transaction on connection #0
await c0.QueryAsync(@"
begin transaction
select * from mytable with (tablockx, holdlock)
");
// This query on connection #1 is blocked by connection #0
var blockedTask = c1.QuerySingleAsync<int>("select count(*) from mytable");
// Strangely, this second query is blocked as well
var requests = await c1.QueryAsync(@"
select session_id, cpu_time, reads, logical_reads
from sys.dm_exec_requests r
");
// We don't get here unless you swap `c1` for `c2` in the last query, making
// it run on it's own connection, thus requiring VIEW SERVER STATE to be useful
requests.Dump();
await blockedTask;
您只需要一个带有任何随机表的数据库来应用它。
【问题讨论】:
标签: sql-server ado.net