2009-03-19 3 views
0

У меня есть приложение-приложение, которое отслеживает изменения каталога.Как лучше избегать нескольких вложений?

Приложение-служба будет внимательно отслеживать каталог. Вот как это делает вещь:

  1. сна X минут
  2. сканирования через каталог, увидеть, есть ли новые дополнения
  3. Launch один поток в одно добавление
  4. Повторить 1-3

Одна из вещей, которые она делает, заключается в том, что она вставляет запись в базу данных. Теперь, поскольку несколько потоков могут работать одновременно, вполне возможно, что два потока вставляют запись одновременно.

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

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

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

P/S: Я пишу службу .Net, которая ведет переговоры с базой данных MySQL.

+0

Зачем вы запускаете сервис при смене файла? Почему бы не позволить службе смотреть каталог с помощью FileSystemWatcher = Если это действительно сервис, он должен выполняться в фоновом режиме и просыпаться, когда что-то происходит. Затем вы можете контролировать параллельные вставки по желанию вашего сердца ... –

+0

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

ответ

1

Я бы посмотрел сначала на то, почему вы хотите это сделать. Обычно приложения работают так, нет проблем с двумя клиентами, делающими вставки одновременно (ну, кроме неправильных подходов в коде).

Также решение будет отличаться в зависимости от сценария. Один из вариантов - иметь очередь сообщений Microsoft (MSMQ) и перемещать вставки из этих служб, поэтому загрузка вложений управляется процессом, который читает форму очереди.

Обновление 1: Я все еще не понимаю, почему вы хотите, чтобы вставки не запускались параллельно (и из того, что я читал в других ответах, которые, как я полагаю, делают другие). Процитирую 2 из ваших комментариев по этому поводу:

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

Ant другой:

Это потому, что перед введением, есть и другие длинные работы, которые требуют параллельности. Только тогда, когда во время вставки требуется последовательный доступ.

Если я прочитаю только первый, я бы на самом деле подумал, что это причина, по которой они хотят их параллельно. Вы хотите сделать с ними как можно быстрее. Переход последовательных будет фактически увеличить время, чтобы сделать вставки, так что есть больше времени, когда может произойти скачок мощности.

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

Для встроенной поддержки у вас может быть случай для распределенной транзакции, которая также включает в себя файловую систему (мс смотрел на файловую систему, но я не помню, если они когда-либо делали что-то на новой ОС). Распределенные транзакции - это боль, которую нужно настроить (msdtc и доступ к используемым портам).

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

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

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

Ps. если это так, трудно сказать из вопроса. Возможно, вы захотите открыть другой вопрос о длительных процессах и/или автоматических попытках.

0

Если у вас установлено несколько служб Windows, просматривающих одну и ту же папку или если у вас многопотоковая служба Windows, вы получите несколько одновременных вставок. В противном случае вам не нужно беспокоиться.

+0

Да, это в данном случае: у меня есть несколько служб, работающих одновременно. – Graviton

1

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

[EDIT] Вы боитесь силового удара. Где? На сервере или на клиенте? Вот ваши варианты:

  1. Аварийный сигнал сервера. Просто попросите клиентов проверить код ошибки для «потеря связи» и попросить их повторить их вставку до тех пор, пока она не удастся. Чтобы выяснить этот код ошибки, либо выключите сервер посередине вставки, либо вытащите сетевой кабель вашего клиента (или и то, и другое, иногда вы получаете разные ошибки для непредвиденных сетевых проблем).

  2. Клиентский сбой (гораздо более вероятно, поскольку клиенты обычно являются недорогими ПК. Если у пользователей есть доступ к нему, он в конечном итоге будет заражен вирусом или файловая система будет повреждена, у него закончится ОЗУ, кто-то установит что-то «классное», которое уничтожит жизненно важную DLL или что-то еще). В этом случае вам нужно снова запустить клиента, проверить, что уже было вставлено (с помощью ключа приложения), и продолжить оттуда.

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

+0

Мне не нужна одновременная вставка, потому что если есть скачок напряжения, я не хочу, чтобы вся вставка шла вниз. – Graviton

+0

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

+0

Буквально * десятилетия работы превратились в базы данных, которые хорошо справляются с такими (посмотрите «ACID»). База данных * не * будет вашей проблемой. – kquinn

0

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

[EDIT]

Это потому, что перед введением, есть и другие длинные работы, которые требуют параллельности. Только тогда, когда во время вставки требуется последовательный доступ.

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

+0

Это потому, что перед вставкой существуют другие длительные задания, требующие параллелизма. Только тогда, когда во время вставки требуется последовательный доступ. – Graviton

0

Как многие говорили раньше: это плохая вещь. Это искусственно создаст узкое место.

Но если вы действительно хотите сделать это, вот ваши варианты:

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

b) если a) недостаточно узкого места для вашей цели, вы должны использовать отдельный замок. В зависимости от вашей среды для этого может быть специальный api (например, java concurrency api).

c) Если это не доступно или вам не нравится, вы можете использовать механизмы блокировки базы данных: создать таблицу с одной строкой в ​​ней. На каждой вкладке сделайте следующее: - прочитайте специальную таблицу «для обновления». Это (в большинстве настроек базы данных) не позволит другим сеансам делать то же самое. - сделайте вставку. - совершить. Это освободит блокировку и позволит продолжить следующую сессию.

И точно так же, как напоминание: Это точно противоположное тому, что один пытается достичь нормально: Разрешение столько потоков, как можно работать без помех

0

Я думаю, что лучший вариант здесь последовать совету Аарона и имеют потоки сообщают после обработки каждого файла; затем обновить базу данных из однопоточного «менеджера».

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

Однако в одном из ваших комментариев говорится, что работает несколько служб. Это правда? Несколько служб Windows просматривают один и тот же каталог и многопоточность обработки? Зачем? Думаю, вам лучше защитить эту архитектуру, чтобы получить лучшие ответы.