Незавершенное чтение SQL Server блокирует транзакции

У меня есть рабочая очередь в SQL, управляемая некоторыми службами, которые считывают записи для обработки READPAST запросами.

Недавно я добавил пользовательский интерфейс для проверки статуса очереди, который использует READ UNCOMMITTED запросы NHibernate на C #. Совершенно не критично, что они вернули мне правильные числа, просто указание на то, как далеко продвинулась обработка.

/* 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, говорит об этом (вопрос задает Майкл не я):

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.


person Michael    schedule 01.08.2013    source источник
comment
С чисто точки зрения написания TSQL / запросов, я бы добавил модификатор (nolock) в каждую таблицу в запросе, но я не уверен, как это сделать с помощью NHibernate.   -  person ganders    schedule 01.08.2013
comment
Можете ли вы включить определение таблицы?   -  person brian    schedule 01.08.2013
comment
@brian Вот расстановка стола. Меня убивает внешний ключ?   -  person Michael    schedule 02.08.2013
comment
Создают ли запросы с незафиксированными чтениями высокую нагрузку на систему? Может быть, полная загрузка ввода-вывода? Или ваш код не может фактически использовать уровень изоляции чтения незафиксированных. Подтвердите используемый уровень, запустив это: stackoverflow.com/questions/1038113/ Или используйте Profiler, чтобы убедиться, что установлен правильный уровень изоляции.   -  person usr    schedule 02.08.2013
comment
@Майкл. Может быть, но я недостаточно знаю о столе. Можете ли вы включить определение любого некластеризованного индекса (ов) в QueueItem? Кроме того, какой запрос вы пытаетесь выполнить?   -  person brian    schedule 02.08.2013
comment
вы используете управление версиями строк? с набором управления версиями строк этого не должно происходить - с другой стороны, без управления версиями строк у меня был аналогичный опыт ...   -  person Linky    schedule 08.08.2013
comment
@Linky Посмотрев на эти ссылки, я почти уверен, что не использует управление версиями строк. Я знаю, что могу исправить свою настройку; В основном я хочу знать, почему он не работает как есть.   -  person Michael    schedule 08.08.2013


Ответы (1)


Я не эксперт по NHibernate, но вы должны попытаться добавить NOLOCK к своим статусным запросам; используйте SetLockMode в NHibernate.

  1. Уменьшите количество индексов, похоже, каждый столбец проиндексирован.
  2. Вы не используете кластерный индекс, добавьте уникальный кластерный индекс в столбцы JobID, ID.
person Joe Perkins    schedule 07.08.2013