从资源池保留的sql和表设计

时间:2019-04-25 14:44:41

标签: sql

好的,我们有N个消息队列,它们是一个池,我们希望允许服务器保留1个消息队列。

我在想桌子

  • id(主键)
  • 保留作业名称(如果可用,则为空)

然后,每个队列有1行。问题是我可以执行一个SQL查询来查找1个可用队列并将其更新为我的工作名称。

update jobname='myjob' where reservation jobname= null

将更新所有行。如何更新最多1行?

谢谢, 院长

2 个答案:

答案 0 :(得分:0)

UPDATE Table SET Jobname = 'Something' 
      WHERE ID = (SELECT MAX(ID) FROM Table WHERE Jobname IS NULL)

答案 1 :(得分:0)

我认为更好的解决方案是拥有3张桌子

由于未指定RDBMS,因此假设使用MySQL,但通常可以将其改编为其他版本。

Simple Queue Reservation ERD

此结构具有许多小的但有价值的功能,包括:

  • 将工作与工作预约区分开(如果没有的话) 可用的队列?)重试可以从最早的createdAt
  • 作业开始
  • 队列状态允许准备一个队列或接收一个 更改状态即可离线
  • queue_job提供按作业的审核跟踪和队列保留的历史记录

使用方法

通过插入startAt的{​​{1}}和NOW()的queue_job行,作业可以保留队列 endAt,具体取决于RDBMS,应将其设置为最大允许的DateTime。我在这里使用perpetuity

完成一项工作后,将该queue_job的endAt日期更新为NOW。

DDL

'9999-12-31'

测试数据和示例查询   A DB-Fiddle of this structure

测试数据

 CREATE TABLE `job` (
     `id` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
     `name` VARCHAR(40),
     `createdAt` TIMESTAMP,
     CONSTRAINT `PK_job` PRIMARY KEY (`id`)
 )
 ENGINE=InnoDB;

 CREATE TABLE `queue` (
     `id` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
     `name` VARCHAR(40),
     `status` TINYINT UNSIGNED,
     CONSTRAINT `PK_queue` PRIMARY KEY (`id`)
 )
 ENGINE=InnoDB;

 CREATE TABLE `queue_job` (
     `id` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
     `queue_id` INTEGER UNSIGNED,
     `job_id` INTEGER UNSIGNED,
     `startAt` DATETIME,
     `endAt` DATETIME,
     CONSTRAINT `PK_queue_job` PRIMARY KEY (`id`)
 )
 ENGINE=InnoDB;

查询

 # Test Data
 INSERT INTO queue (name, status) VALUES ('Queue 1', 1), ('Queue 2', 1), ('Queue 3', 1), ('Queue 4', 0);
 INSERT INTO job (name) values ('Big Job');
 INSERT INTO job (name) values ('Little Job');
 INSERT INTO job (name) values ('Big Job');
 INSERT INTO job (name) values ('Little Job');
 INSERT INTO job (name) values ('Medium Job');
 INSERT INTO queue_job (queue_id, job_id, startAt, endAt) VALUES (2, 1, DATE_ADD(NOW(), INTERVAL -1 SECOND), DATE_ADD(NOW(), INTERVAL -1 SECOND));
INSERT INTO queue_job (queue_id, job_id, startAt, endAt) VALUES (3, 2, DATE_ADD(NOW(), INTERVAL -1 SECOND), DATE_ADD(NOW(), INTERVAL -1 SECOND));
 INSERT INTO queue_job (queue_id, job_id, startAt, endAt) VALUES (3, 3, DATE_ADD(NOW(), INTERVAL -5 MINUTE), DATE_ADD(NOW(), INTERVAL -3 MINUTE));

 INSERT INTO queue_job (queue_id, job_id, startAt, endAt) VALUES (2, 4, DATE_ADD(NOW(), INTERVAL -1 SECOND), '9999-12-31');