2011-08-15 28 views
6

假設我正在編寫一個應用程序,我需要從服務器實時獲取通知,並且讓我們假設這些通知已存儲在一個MySQL數據庫上。 對於我來說,我不得不繼續輪詢MySQL服務器(不斷重複相同的選擇 查詢,直到我實際得到結果),但我認爲這是非常有效的方式做到這一點,因爲大部分時間選擇將轉向空了。如果我經常這樣做,那麼服務器上的壓力就會不合理,如果我這麼做的話,很少會有很晚的通知。 所以我想知道是否有一種方法來說,一個MySQL查詢阻塞,直到符合條件的結果變爲可用。的有沒有辦法讓MySQL等待匹配要插入的條件的行

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

,而不是有沒有未讀的通知返回一個空列表,它反而會等到其實有未讀通知回到

回答

8

我建議使用producer consumer模式,用新的表作爲實施「工作隊列」。不需要存儲過程,因爲觸發器非常簡單。

  1. 觸發器將填充工作隊列
  2. 代碼會輪詢工作隊列表。由於表格非常小​​,因此查詢速度快且負載低。
  3. 代碼會做任何你需要,完成後從表中刪除行 - 保持它儘可能小

創建具有notification的ID進行處理和「處理狀態」列的表,例如:

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秒(此次停頓需要與通知的峯值到達率大致相同 - 您需要調整此值以平衡work_queue大小和服務器負載)
  6. 轉到1.

如果您有一個進程輪詢,則不需要鎖定問題。如果你有多個進程輪詢,你需要處理競爭條件。

+0

有趣的想法,我認爲除了民意測驗之外沒有別的辦法, 謝謝你的支持:) –

+0

沒有別的辦法,所以你想讓你的民意測驗儘可能快。我不得不說,這是我一生中贏得了聲譽的最艱難的10點:) – Bohemian

+0

我想用一個內存中的表可能是一個很好的推動這裏 –

相關問題