我在 SQL 中有一个工作队列,由一些服务管理,这些服务读出要处理READPAST
查询的条目。
我最近添加了一个 UI 来检查在 C# 中使用READ UNCOMMITTED
NHibernate 查询的队列状态。他们给我正确的数字并不重要,只是表明处理过程有多远。
/* 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
。