2011-08-15 5 views
6

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

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

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

ответ

8

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

  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. Сон 1 секунда (эта пауза должна быть примерно такой же, как и максимальная скорость поступления уведомлений - вам нужно настроить ее для баланса между размером рабочей_игрузки и нагрузкой сервера)
  6. goto 1.

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

+0

интересная идея, я беру ее, нет другого способа, кроме опроса, спасибо за ancwer :) –

+0

нет другого выхода, поэтому вы хотите сделать свой опрос как можно быстрее.Я должен сказать, что это самые жесткие 10 баллов репутации, которые я когда-либо зарабатывал :) – Bohemian

+0

Я полагаю, что использование таблицы памяти может быть хорошим стимулом здесь –