4

我在 SQL 中有一个工作队列,由一些服务管理,这些服务读出要处理READPAST查询的条目。

我最近添加了一个 UI 来检查在 C# 中使用READ UNCOMMITTEDNHibernate 查询的队列状态。他们给我正确的数字并不重要,只是表明处理过程有多远。

/* called from a foreach (I know... I could get them all at once with SQL) */
IQuery query = Persistence.CreateQuery(
    "select count(qi) from QueueItem qi where qi.Job = :job");
query.SetEntity("job", thisJob);
using(Persistence.ReadUncommitted())
{
    return (long)query.UniqueResult();
}

问题是这些状态查询已经开始导致超时。有时他们自己失败了;有时它们会导致队列操作失败。

主要的MSDN 文档说,如果我更改架构,仍然可以锁定,但我不是。

另一方面,显然为 Microsoft 的 SQL Server 团队工作的Marcel van der Holst就这个问题(提出问题的迈克尔不是我):

READ UNCOMMITTED事务不会占用任何数据库锁,但仍需要读取数据库页面才能读取实际数据。如果其他事务同时写入这些页面,它们可能会在两者之间造成一些阻塞。在引擎内部,我们不允许任何事务在写入过程中读取页面(我们使用锁存器来保证这一点)。如果在进行大查询时正在写入大量事务,则大读取可能仍会被阻塞。

我做错了什么吗?我应该改变什么来停止阻塞?

架构

create table QueueItem(
    ID int identity(1,1) not null,
    JobID int not null,
    PersonID int not null,
    DateProcessed datetime null,
    Error varchar(max) null,
    constraint [PK_QueueItem] primary key nonclustered (ID)
)

alter table QueueItem
add constraint [FK_QueueItemsToJobs] foreign key (JobID)
references Job (ID)

非聚集索引:

JobID, DateProcessed, PersonID, ID (Non-Unique, Non-Clustered)
DateProcessed, JobID, PersonID (Non-Unique, Non-Clustered)
JobID, ID (Unique, Non-Clustered)
JobID, PersonID, ID (Unique, Non-Clustered)
PersonID, JobID, ID, DateProcessed (Unique, Non-Clustered)
ID (Unique, Non-Clustered)

在实践中

我减少了读取次数,因为它不会让事情变慢,但我仍然很好奇为什么可能会阻塞 with READ UNCOMMITTED

4

1 回答 1

0

我不是 NHibernate 方面的专家,但您应该尝试将 NOLOCK 添加到您的状态查询中;在 NHibernate 中使用 SetLockMode。

  1. 减少索引的数量,看起来每一列都有索引。
  2. 您没有使用聚集索引,请在列 JobID、ID 上添加唯一聚集索引。
于 2013-08-07T23:05:50.537 回答