2011-08-15 7 views
6

私は、アプリケーションからリアルタイムで通知を受け取る必要があると思いますが、それらの通知が保存されているとしましょうmysqlデータベースで。 私はそれらを得るために私はmysqlサーバをポーリングし続ける必要があります(私は実際に結果が得られるまで同じ選択を繰り返し続けます)。しかし、私はそれが非常に不十分な方法であることを理解しています。空になる。もし私がそれを頻繁に行うなら、通知が非常に遅くなることはめったにありません。 したがって、条件に一致する結果が利用可能になるまで、mysqlクエリをブロックする方法があるかどうかは疑問でした。未読の通知がない場合は、実際にMySQLが条件を満たす行が挿入されるのを待つ方法がありますか?

答えて

8

を返すために、未読の通知があるまで

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

代わりに空のリストを返すので、それは代わりに待って、私は、新しい表を使って実施producer consumerパターンを、使用することをお勧めします"作業待ち行列"。トリガは非常に簡単なので、ストアドプロシージャの必要はありません。

  1. トリガは、作業キューに作業キュー・テーブルをポーリングします
  2. コードを取り込みます。テーブルが非常に小さいため、クエリは高速かつ低負荷になります。
  3. コードは、必要なものは何でもして終了したときに、テーブルから行を削除するだろう - 、

できるだけ処理する notificationのIDと「処理状況」列を持つ表を作成すると、小さなそれを維持例えば:

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 ; 

あなたのタラ:

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

は、作業キュー表を移入する簡単なトリガーを作成します。あなたは(あなたが失敗したアイテムをどうするかを把握する必要があります)notifications where id = <row.notification_id>

  • delete from work_queue where id = <row.id>またはupdate work_queue set status = 'failed' where id = <row.id>のいずれかに必要なものですか

    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. :eは擬似コードを持っているでしょう
    4. スリープ1秒(このポーズは、通知のピーク到着率とほぼ同じにする必要があります。これを調整して、work_queueサイズとサーバー負荷のバランスを調整する必要があります)
    5. goto 1.

    プロセスポーリングが1つの場合、ロックの心配はありません。複数のプロセスがポーリングしている場合は、競合状態を処理する必要があります。

  • +0

    興味深いアイデアは、ポーリング以外の方法はありません。 ancwerに感謝します:) –

    +0

    他の方法はありませんので、できるだけ早く投票したいと思っています。私はそれが私が今までに得た評判の最も厳しい10点だと言わなければならない:) – Bohemian

    +0

    私はメモリテーブルを使うと良いと思う。 –

    関連する問題