@fanofmarta
Учу Flutter

Как предотвратить двойную обработку одной строки из базы?

Синьоры и синьориты, приветствую.

Есть таблица в БД (условно):
Название Время обработки
Строка 1 10:00
Строка 2 10:01
Строка 3 10:02
............................
Строка N 23:59

Есть условно 10 скриптов, одновременно запускающихся по крону.
10 скриптов это 10 одинаковых PHP файлов, которые отличаются только авторизационными данными.

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

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

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

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

Ситуация, когда 2 скрипта обратятся к одной строке более чем возможна.
И между двумя запросами SELECT и UPDATE в любом случае пройдет какое-то время.

Как не допустить ситуации, когда несколько скриптов одновременно обратились к одной и той же строке таблицы и взяли ее в работу?

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

P. S. Я знаю, что ничего не знаю. Знаю, что так делать неправильно. Знаю, что мои познания в архитектуре болтаются около нуля.
Но я хочу решить именно эту задачу наиболее эффективно.
Я читаю книги и учу матчасть.
Если хотите уведомить меня о том, что мне лучше бросить программирование и ничего сюда не писать - не тратьте время.
  • Вопрос задан
  • 166 просмотров
Решения вопроса 1
Пригласить эксперта
Ответы на вопрос 4
@vism
нужно писать уникальный ИД и по нему выбирать строку.
Т.е.
1. в скрипте генерируете хэш
2. делаете апдейт с этим хэшем
3. по этому хэшу уже берете строку и отрабатываете.
Ответ написан
toxa82
@toxa82
Используйте LOCK TABLES tbl_name WRITE, тогда для других потоков блокируется даже чтение.
Ответ написан
FanatPHP
@FanatPHP
Чебуратор тега РНР
Комментировать
@MaLuTkA_UA
Предположительно у вас таблица содержит задачи в формате:
id | execute_in | executed_at
1 | 10:00 | null
2 | 10:01 | null

Так вот чтобы выбрать на языке postgresql, можно выполнить следующий запрос
UPDATE jobs SET executed_at = now() WHERE id = (SELECT id FROM jobs WHERE execute_in <= now() AND executed_at is null LIMIT 1) AND executed_at is null RETURNING id

Тем самым мы обновляем только одну запись и после ее обновления получаем еë id, или всю запись
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы