【问题标题】:SQL Server Read Uncommitted is blocking transactionsSQL Server Read Uncommitted 阻塞事务
【发布时间】: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


【解决方案1】:

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

  1. 减少索引的数量,看起来每一列都被索引了。
  2. 您没有使用聚集索引,请在 JobID、ID 列上添加唯一聚集索引。

【讨论】:

    猜你喜欢
    • 2017-12-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-23
    • 1970-01-01
    • 2017-11-10
    • 1970-01-01
    相关资源
    最近更新 更多