【发布时间】:2013-08-02 18:25:27
【问题描述】:
我在 SQL 中有一个工作队列,由一些服务管理,这些服务读出要处理 READPAST 查询的条目。
我最近添加了一个 UI 来检查队列状态,该 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();
}
问题是这些状态查询已经开始导致超时。有时他们自己失败了;有时它们会导致队列操作失败。
main MSDN documentation 说如果我更改架构,仍然可以锁定,但我没有。
另一方面,Marcel van der Holst 显然为 Microsoft 的 SQL Server 团队工作,says this 在这个主题上(提出问题的迈克尔不是我):
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)
实践中
我已经减少了读取次数,因为它不会让事情变慢,但我仍然很好奇为什么 READ UNCOMMITTED 可能会阻塞。
【问题讨论】:
-
从纯粹的 TSQL/查询编写的角度来看,我会在查询中的每个表中添加“(nolock)”修饰符,但我不确定如何通过 NHibernate 来实现。
-
可以包含表定义吗?
-
@brian 这是表格设置。外键是什么在杀死我?
-
读取未提交的查询是否会给系统带来高负载?也许是完整的 IO 负载?或者您的代码未能实际使用读取未提交的隔离级别。通过运行以下命令确认正在使用的级别:stackoverflow.com/questions/1038113/… 或使用 Profiler 确认正在设置正确的隔离级别。
-
@迈克尔。也许吧,但我对这张桌子还不够了解。您能否在 QueueItem 上包含任何非聚集索引的定义?另外,您要运行的查询是什么?
标签: sql sql-server nhibernate read-uncommitted