gpt4 book ai didi

具有多个选择线程的 MySQL 生产者消费者

转载 作者:行者123 更新时间:2023-11-29 06:35:04 26 4
gpt4 key购买 nike

我有以下情况:

有一个表包含要处理的不同“作业”和多个使用这些作业的工作线程。因为我不想在完成后删除这些作业,所以我将为该记录设置一个“完成”标志。

所以实际上我有以下工作流程(针对每个处理线程)

  1. 选择第一个不完整的记录
  2. 处理作业
  3. 设置“完成”标志

如何防止其他线程使用相同的作业(因为将其设置为“完成”需要一段时间)。此外,仅在第二步更新“完成”标志将导致某些作业被处理两次,因为可能有大量线程处理少量作业。

最简单的方法是只锁定记录(是的,我正在使用 InnoDB),这样其他线程就不能只读取那条记录集。这很容易通过“FOR UPDATE”实现,但是这将锁定整个表以供将来选择,所有其他“FOR UPDATE”选择必须等到第一个完成。

谁能告诉我,如何在不延迟所有其他线程的情况下解决这种情况?所以实际上一个选择(也可以被 LIMIT 1 限制)应该只“看到”非锁定行......

示例表结构如下所示

JobID | completed
123 | 0
124 | 1
125 | 0

用大约 10-50 个线程做一个简单的

SELECT JobID from jobs WHERE completed = 0;
UPDATE jobs SET completed = 1 WHERE JobID = ?;

感谢任何提示和技巧!

最佳答案

我为您提供了一个实用的解决方案,我已经在我工作场所的一个项目中看到了这个解决方案。不要只使用 0 和 1 表示未完成和已完成,而是扩展您的集合以包含更多案例。

我们将该列称为状态。以下是该列的不同值以及作业的相应状态。

  1. 当状态为 0 时,作业尚未被任何工作线程拾取。
  2. 当状态为 1 时,作业已被工作线程拾取并正在处理中。
  3. 当状态为 2 时,作业失败。 (您应考虑处理失败的可能性。)
  4. 当状态为 3 时,作业已完成。

你的线程应该包含这样的逻辑,它只选择状态为 0 的作业并将状态更改为 1。这将不允许其他线程选择那些正在处理的作业。当作业完成时,状态设置为 3,如果作业失败,状态设置为 2。然后线程可以继续寻找另一个尚未完成的作业。

您也可以要求线程考虑选择状态 2 的作业,但您必须定义逻辑来指定有限的重试次数。

编辑:

经过 long discussion ,我们一起偶然发现了解决方案。当“工作”是一个需要一些时间才能完成的过程时,我上面的回答在更普遍的状态下是好的。但 OP 的问题并非如此。

所以最终有效的解决方案是这样的:

BEGIN 
SELECT * FROM Jobs WHERE JobID = (SELECT * FROM Jobs WHERE completed = 0 LIMIT 1) LOCK IN SHARE MODE;
UPDATE Jobs SET completed = 1 WHERE JobID = (PREVIOUS ID);
COMMIT;

关于具有多个选择线程的 MySQL 生产者消费者,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25427215/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com