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

Тема в разделе "Как сделать...", создана пользователем chang, 26 мар 2011.

  1. chang

    chang

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

    id name option

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

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

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


    собственно вопрос: как организовать изъятие данных таким образом чтоб потоки/приложения не брали уже взятые другим потоком данные?
    ну и чтоб в последствии были обработаны все данные ?
     
  2. dandandan

    dandandan

    Регистр.:
    7 авг 2008
    Сообщения:
    990
    Симпатии:
    267
    Добавьте еще один столбец. В него пишите значение 0/1 (были обработаны данные или нет). Затем после обработки всех данных флаг обнуляйте.
     
  3. chang

    chang

    Регистр.:
    20 ноя 2009
    Сообщения:
    364
    Симпатии:
    117
    dandandan

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

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

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

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

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

    + их обновлять еще при каждом запросе ... хотелось бы как-то минимизировать нагрузку.
     
  4. horpah

    horpah

    Регистр.:
    21 июн 2010
    Сообщения:
    200
    Симпатии:
    55
    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
     
    latteo и chang нравится это.
  5. chang

    chang

    Регистр.:
    20 ноя 2009
    Сообщения:
    364
    Симпатии:
    117
    horpah, хм, а мне нравится

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

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

    вариант влоб: добавить поле "время изъятия данных потоком" ну и по крону освобождать все данные которые заблочены более чем t времени, но как-то не очень мне это решение
     
  6. horpah

    horpah

    Регистр.:
    21 июн 2010
    Сообщения:
    200
    Симпатии:
    55
    Если несколько серверов, тогда делать привязку сервер-pid. И в начале нового потока "спрашивать" у сервера, открывшего поток, жив ли он еще. Если сервер не ответит (лежит) или ответит "сдох поток", то освобождать записи.
     
  7. exn

    exn Постоялец

    Регистр.:
    22 янв 2010
    Сообщения:
    146
    Симпатии:
    23
    пфу блин, какие же это потоки , это чушь, граждане.

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