У меня есть таблица SQL Server, полная заказов, которые моя программа должна «следить» (позвоните в веб-сервис, чтобы узнать, что с ними что-то сделано). Мое приложение многопоточное и может иметь экземпляры, запущенные на нескольких серверах. В настоящее время, каждый так часто (по таймеру Threading), процесс выбирает из списка «неподтвержденных» ордеров 100 случайных чисел (ORDER BY NEWID()
) и маркирует все, которые возвращаются успешно.Обработка очереди базы данных по нескольким потокам - советы по дизайну
Проблема заключается в том, что между потоками и между различными процессами существует много перекрытий, и они не гарантируют, что новый заказ будет проверен в ближайшее время. Кроме того, некоторые заказы никогда не будут «подтверждены» и будут мертвы, а это значит, что они мешают заказам, которые необходимо подтвердить, замедляя процесс, если я буду продолжать их выбирать снова и снова.
Я бы предпочел, чтобы все выдающиеся приказы систематически проверялись. Я могу думать о двух простых способов сделать это:
- Приложение выбирает один заказ, чтобы проверить, в то время, проходя в последнем порядке проверьте его в качестве параметра, и SQL Server руки обратно на следующий заказ, это неподтвержденные. Больше запросов к базе данных, но это гарантирует, что каждый заказ проверяется в разумные сроки. Однако разные серверы могут повторно проверять один и тот же порядок подряд, без необходимости.
- SQL Server отслеживает последний заказ, который он попросил проверить, может быть, в таблице, и дает уникальный заказ для каждого запроса, увеличивая счетчик. Это связано с сохранением последнего порядка где-то в SQL, чего я хотел избежать, но он также гарантирует, что потоки не будут лишним проверять одни и те же заказы одновременно.
Есть ли какие-либо другие идеи, которые мне не хватает? Это даже имеет смысл? Дайте мне знать, если мне нужно уточнить.
РЕЗУЛЬТАТ:
То, что я в конечном итоге делаю добавлял столбец LastCheckedForConfirmation к моему столу с готовыми заказами в нем, и я добавил хранимую процедуру, которая обновляет один, неподтверждённой строки с GETDATE() и выдает номер заказа, чтобы мой процесс мог проверить его. Он закручивает столько из них, сколько может (учитывая количество потоков, которые процесс готов запустить), и использует хранимую процедуру для получения нового OrderNumber для каждого потока.
Чтобы справиться с проблемой «Не пробуйте строки слишком много раз или когда они слишком старые», я сделал следующее: SP вернет строку только в том случае, если «Время с последней попытки»> «Время между созданием и last try ", поэтому каждый раз это займет в два раза больше времени, прежде чем он снова попытается - сначала он ждет 5 секунд, затем 10, затем 20, 40, 80, 120, а затем после 15 попыток (6 часов) он дает в этом порядке, и SP никогда больше не вернет его.
Спасибо за помощь, все - я знал, что я делаю это было не так идеально, и я ценю ваши указатели в правильном направлении.
Вариант 2 звучит гораздо более предпочтительным для меня на первый взгляд. Что происходит с мертвыми орденами? Получают ли они подтвержденные мертвые в какой-то момент или просто вымерли? –
@Martin Smith: нет официального тайм-аута - они просто не создаются на удаленной системе (которая принадлежит поставщику), и поэтому мне нужно в какой-то момент отказаться, но это сколь угодно долго. Ничто никогда не становится «подтвержденным мертвым» как таковым, и это делает его трудным, хотя, поскольку большинство заказов создаются (и подтверждаются) в течение нескольких минут, я, вероятно, могу рассматривать что-нибудь старше, чем один день, как подтвержденный мертвый. – SqlRyan