Каков правильный уровень изоляции, чтобы включить это решение для нескольких читателей? - PullRequest
3 голосов
/ 04 марта 2009

У меня есть таблица базы данных, содержащая очередь рабочих элементов, обрабатываемых одновременно несколькими читателями, с такими требованиями:

  • Каждый элемент должен обрабатываться только одним читателем.
  • Если по какой-либо причине произойдет сбой считывателя, элемент должен быть возвращен в очередь для обработки другим считывателем.

Вот псевдокод возможного решения, каждый читатель сделает следующее:


1) Читать следующий элемент из очереди и хранить его где-нибудь локально.

2) НАЧАЛО СДЕЛКИ

3) Удалите элемент, чтобы другие читатели не видели его. Если удаление не удалось, это означает, что другой работник уже вытащил элемент, поэтому вернитесь к шагу 1.

4) Обработать элемент (хранится локально на шаге 1). Это может быть долго.

5) СОВЕРШЕНИЕ СООБЩЕНИЯ: удаление элемента выполнено, перейдите к шагу 1 для обработки следующего элемента

OR

6) ROLLBACK TRANSACTION (явный откат или ошибка считывателя): удаление элемента откатывается и возвращается в очередь для другого считывателя


У меня вопрос: какой самый низкий уровень изоляции я должен обеспечить, чтобы после шага 3 (удаление элемента) другие читатели не могли его увидеть? Под самым низким я подразумеваю, что хочу максимизировать параллелизм при сохранении целостности.

Примечание. Я использую SQL Server 2005, если это имеет значение (я думаю, что это не зависит от продукта, верно?)

Любые другие отзывы об этом подходе в целом приветствуются.

Ответы [ 3 ]

1 голос
/ 04 марта 2009

Если после удаления элемента из механизма «Очередь» ни один prcess не сможет получить к нему доступ, вам не нужно оставлять транзакцию открытой, пока вы фактически обрабатываете элемент.

ПОВТОРЯЮЩАЯ ЧТЕНИЕ уровень изоляции:

Указывает, что операторы не могут читать данные, которые были изменены, но не совершено другими транзакциями и что никакие другие транзакции не могут изменить данные, которые были прочитаны текущая транзакция до текущей транзакция завершена.

Общие блокировки размещаются на всех данных читать каждое утверждение в сделки и проводятся до транзакция завершена. Это мешает другие транзакции от изменения любого строки, которые были прочитаны текущая транзакция. Другой транзакции могут вставлять новые строки, которые соответствовать условиям поиска заявления, выданные действующим сделка. Если текущий транзакция затем повторяет утверждение он получит новые строки, которые приводит к фантомному чтению. Так как общие блокировки удерживаются до конца транзакция вместо того, чтобы быть выпущенным в конце каждого утверждения, параллелизм ниже, чем по умолчанию ЧИТАЙТЕ ЗАВЕРШЕННЫЙ уровень изоляции. использование эта опция только при необходимости.

1 голос
/ 04 марта 2009

Альтернативный метод для обработки этого, который я использовал:

  1. Каждый рабочий элемент имеет столбец для State и другой для ReaderID. Состояние может быть «новый», «активный» или «полный». (Я также использую 'E'rror.)

  2. Каждый из читателей имеет свой собственный идентификатор.

  3. Первым действием Reader является ОБНОВЛЕНИЕ первого поставленного в очередь элемента с состоянием 'N' с помощью одного оператора SQL, который устанавливает для состояния "A" и ReaderID для себя.

  4. Затем устройство Reader обрабатывает рабочий элемент и, когда оно выполнено, устанавливает состояние «C».

В ваших целях вы избегаете проблем с изоляцией, поскольку действие проверки выполняется в одном утверждении.

SQL будет выглядеть примерно так:

Очередь обновлений
SET State = 'A', ReaderID = @ myWorkerID
WHERE queueid = (ВЫБЕРИТЕ MIN (queueid) ОТ очереди WHERE состояние = 'N')

0 голосов
/ 04 марта 2009

Если вы используете в своем запросе блокировку уровня строки и оператор readpast, вы можете выбрать только те строки, которые не заблокированы.

Похоже на это.

ВЫБРАТЬ очередь ОТ очереди с (rowlock, xlock, readpast) ГДЕ состояние = 'N'

Я предлагаю вам прочитать подсказки по блокировке в SQL-сервере, которые очень вам помогут.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...