выбор из БД "пачками" данных в многопоточном приложении

chang

Постоялец
Регистрация
20 Ноя 2009
Сообщения
363
Реакции
118
есть некая БД кол-во записей которой может возрасти до 1+ ляма
структура простая ..

id name option

где option может принимать 2 значения 0/1 ( по умолчанию 0)

несколько приложений/потоков должны запрашивать из этой таблицы данные, к примеру пачками по 100 штук
данные должны извлекаться лишь те где option = 0

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


собственно вопрос: как организовать изъятие данных таким образом чтоб потоки/приложения не брали уже взятые другим потоком данные?
ну и чтоб в последствии были обработаны все данные ?
 
Добавьте еще один столбец. В него пишите значение 0/1 (были обработаны данные или нет). Затем после обработки всех данных флаг обнуляйте.
 
dandandan

поток 1 берет пачку записей, в том числе и запись № 10
поток 1 30 минут работает с этой 100 записей

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

ну и в последствии получится что запись №10 была обработана
дважды.

ну а если потоков будет 10-20 штук, то запись №10 могут обработать 10-20 раз ...

-------
добавить еще поле "запись обрабатывается" ?
ну тогда поиск усложнится по трем признакам
option != 0 and были_обработаны_данные_или_нет and запись_обрабатывается

+ их обновлять еще при каждом запросе ... хотелось бы как-то минимизировать нагрузку.
 
1)Добавляется поле PID default 0 - pid процесса занявшего записи.
2)Процесс резервирует пачку данных:
UPDATE table SET pid=$mypid WHERE option=0 AND pid=0 LIMIT X,
где Х - количество записей в пачке.
3) SELECT * FROM table WHERE pid=$mypid
собственно выборка зарезервированной пачки для обработки.

4) По окончании работы потока освобождаем резерв:
UPDATE table SET pid=0 WHERE pid=$mypid

Как показала практика - потоки могут прерываться, причем жестко без права последнего слова. Это я по поводу того, что если например в PHP, зарегистрирована завершающая register_shutdown_function('shutdown'); то на нее возлагать надежду по освобождению записей бессмысленно: убьют так, что до нее дело и не дойдет.

Для хранения pid текущего потока лучше взять новую таблицу table2, чтобы не искать DISTINCT pid в многомиллионной таблице.
При старте нового потока нужно выбрать все pid из этой таблицы и проверить для каждого, не прибит ли данный процесс:
posix_kill(pid,0).
Если поток прибит, то нужно освободить зарезервированные им запсиси:
UPDATE table SET pid=0 WHERE pid=IN(список прибитых pid'ов)
И далее как описано выше.
При выходе не забывать чистить за собой table2:
DELETE from table2 WHERE pid=$mypid
 
horpah, хм, а мне нравится

а если к примеру есть 1 БД, и 2-3 сервера работающие с этой БД и порождающие потоки....

как в таком случае "обезопасить" данные от смерти потока на каком-то из серверов, ( ну или самого смерти самого сервера )

вариант влоб: добавить поле "время изъятия данных потоком" ну и по крону освобождать все данные которые заблочены более чем t времени, но как-то не очень мне это решение
 
horpah, хм, а мне нравится
а если к примеру есть 1 БД, и 2-3 сервера работающие с этой БД и порождающие потоки....
как в таком случае "обезопасить" данные от смерти потока на каком-то из серверов, ( ну или самого смерти самого сервера )
вариант влоб: добавить поле "время изъятия данных потоком" ну и по крону освобождать все данные которые заблочены более чем t времени, но как-то не очень мне это решение
Если несколько серверов, тогда делать привязку сервер-pid. И в начале нового потока "спрашивать" у сервера, открывшего поток, жив ли он еще. Если сервер не ответит (лежит) или ответит "сдох поток", то освобождать записи.
 
пфу блин, какие же это потоки , это чушь, граждане.

делайте нормальное приложение и mutex'ами разруливайте, если оно кластерное то рпц и барабан в руки.
 
Назад
Сверху