Вопрос

Существует небольшая система, в которой таблица базы данных является очередью на MSSQL 2005. Несколько приложений пишут в эту таблицу, а одно приложение читает и обрабатывает в FIFO-формате.

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

Моя идея - расширить таблицу очередей строкой, показывающей, что над ней уже работает процесс. Приложение обработки сначала обновит таблицу своим idetifyer, а затем запросит обновленные записи.

Так что-то вроде этого:

start transaction
update top(10) queue set processing = 'myid' where processing is null
select * from processing where processing = 'myid'
end transaction

После обработки он устанавливает в столбце обработки таблицы что-то еще, например, «выполнено» или что-то в этом роде.

У меня есть три вопроса об этом подходе.

Во-первых: это может работать в этой форме?

Второе: если это работает, эффективно ли это? Есть ли у вас другие идеи по созданию такого дистрибутива?

В-третьих: в MSSQL блокировка основана на строках, но после того, как количество строк заблокировано, блокировка распространяется на всю таблицу. Таким образом, второе приложение не может получить к нему доступ, пока первое приложение не освободит транзакцию. Насколько большим может быть выделение (top x), чтобы не блокировать всю таблицу, а только создавать блокировки строк?

Это было полезно?

Решение

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

Другие советы

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

Кроме того, строка / таблица будет заблокирована только во время выполнения операций обновления и выбора, поэтому я сомневаюсь, что вопрос "строка против таблицы" действительно важен.

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

Сказав все это, я не администратор баз данных, и поэтому мне также будут интересны дополнительные экспертные ответы

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

update mytable with (rowlock) set x=y where a=b

Самая большая проблема с этим подходом состоит в том, что вы увеличиваете количество «обновлений» в таблице. Попробуйте сделать это, используя только один процесс (update + delete) и другие, вставляющие данные в таблицу, и вы обнаружите, что на уровне около миллиона записей он начинает разрушаться.

Я бы предпочел иметь одного потребителя для БД и использовать очереди сообщений для доставки данных обработки другим потребителям.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top