首页 > 解决方案 > 基于 MySQL 的消息队列

问题描述

该表用作具有多个读取器和写入器的消息队列:

CREATE TABLE IF NOT EXISTS MyQueue(
id CHAR(36) PRIMARY KEY NOT NULL, 
at DateTime NOT NULL, 
message TEXT NOT NULL, 
INDEX(at ASC));

我尝试通过使用更新锁来防止重复阅读消息:

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
SELECT message FROM MyQueue WHERE at <= @today ORDER BY at ASC LIMIT 1 FOR UPDATE;
UPDATE MyQueue SET at=@nextDay WHERE at <= @today ORDER BY at ASC LIMIT 1;

(想法是在今天晚些时候在一位读者成功处理后删除消息,或者明天重新处理。)

但看起来一些双重读取仍然是可能的。要注意什么?

标签: mysql

解决方案


它有助于将查询包装到 Tx 中:

START TRANSACTION;
SELECT id, at, message FROM {Table} WHERE at <= @now ORDER BY at ASC LIMIT 1 FOR UPDATE;
UPDATE {Table} SET at=@timeout WHERE at <= @now ORDER BY at ASC LIMIT 1;
COMMIT;

推荐阅读