Есть ли способ для MySQL ждать строк, соответствующих условию, которое будет вставлено

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

list = query ("SELECT * FROM `notifications` WHERE `unread`=1") ;

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

1 ответов


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

  1. триггер заполнит рабочую очередь
  2. код опросит таблицу рабочих очередей. Поскольку таблица будет очень маленькой, запрос будет быстрым и малонагруженным.
  3. код будет делать все, что вам нужно, и удалять строки из таблицы по завершении - держать его как можно меньше

создайте таблицу с идентификатором notification обрабатывается и столбец "статус обработки", например:

create table work_queue (
    id int not null auto_increment,
    notification_id int references notifications,
    status enum ('ready', 'processing', 'failed')
);

создайте простой триггер, который заполняет таблицу рабочей очереди:

delimiter $
create trigger producer after insert on notifications
for each row begin 
    insert into work_queue (notification_id, status) 
    select new.id, 'ready'
    where new.unread;
end; $
delimiter ;

ваш код будет иметь псевдо код:

  1. select * from work_queue where status = 'ready' order by id limit 1
  2. update work_queue set status = 'processing' where id = <row.id>
  3. делать то, что вам нужно notifications where id = <row.notification_id>
  4. или delete from work_queue where id = <row.id> или update work_queue set status = 'failed' where id = <row.id> (вам придется выясните, что делать с неудачными элементами)
  5. Sleep 1 секунда (эта пауза должна быть примерно такой же, как пиковая скорость прибытия уведомлений - вам нужно настроить это, чтобы сбалансировать размер work_queue и нагрузку на сервер)
  6. goto 1.

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