有没有办法让MySQL等待符合条件的行插入

时间:2011-08-15 18:49:15

标签: mysql blocking wait polling long-polling

假设我正在编写一个应用程序,我需要从服务器实时获取通知,并且假设这些通知存储在mysql数据库中。 为了让我得到它们,我必须继续轮询mysql服务器(继续重复相同的选择 查询,直到我实际得到结果)但我认为这是非常无效的方式这样做,因为大多数时候选择将变为空。如果我经常这样做,它在服务器上是不合理的压力,如果我这样做,很少通知会很晚。 所以我想知道是否有办法说一个mysql查询阻止,直到匹配条件的结果可用。

list = query ("SELECT * FROM `notifications` WHERE `unread`=1") ;
如果没有未读通知,

而不是返回空列表,而是等到实际上有未读通知返回

1 个答案:

答案 0 :(得分:8)

我建议使用producer consumer模式,使用新表作为“工作队列”实现。不需要存储过程,因为触发器非常简单。

  1. 触发器将填充工作队列
  2. 代码将轮询工作队列表。因为表格非常小​​,所以查询速度快且负载低。
  3. 代码可以执行您需要的任何操作,并在完成后从表中删除行 - 保持尽可能小
  4. 创建一个表格,其中包含要处理的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. 所需的操作
    5. delete from work_queue where id = <row.id>update work_queue set status = 'failed' where id = <row.id>(您必须弄清楚如何处理失败的商品)
    6. 睡眠1秒(此暂停需要与通知的峰值到达率大致相同 - 您需要调整此值以平衡work_queue大小和服务器负载)
    7. 转到1。
    8. 如果您只进行一次流程轮询,则无需担心锁定问题。如果您有多个进程轮询,则需要处理竞争条件。