【问题标题】:Is there a way for MySQL to wait for rows matching a condition to be insertedMySQL有没有办法等待匹配条件的行被插入
【发布时间】:2011-08-15 18:49:15
【问题描述】:

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

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

如果没有未读通知,它不会返回一个空列表,而是等到实际上有未读通知才返回

【问题讨论】:

    标签: mysql blocking wait polling long-polling


    【解决方案1】:

    我推荐使用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 秒(此暂停需要与通知的峰值到达率大致相同 - 您需要对此进行调整以平衡工作队列大小和服务器负载)
    6. 转到 1。

    如果你有一个单进程轮询,就不需要担心锁定。如果您有多个进程轮询,则需要处理竞争条件。

    【讨论】:

    • 有趣的想法,我认为除了投票之外别无他法,谢谢你的回答:)
    • 别无他法,因此您希望尽可能快地进行轮询。我不得不说,这是我赢得的最艰难的 10 分声誉:)
    • 如果您想减少所有这些轮询的数据库负载,您可以让生产者锁定 work_queue 表以进行读取,并仅在有一些可用工作时解锁它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-12-26
    • 1970-01-01
    • 1970-01-01
    • 2010-11-04
    • 2021-12-11
    • 2019-08-19
    • 1970-01-01
    相关资源
    最近更新 更多