MySQL 中并发工作线程的原子读取和更新

Jos*_*osh 5 mysql sql transactions

假设我有多个工作人员可以同时读取和写入 MySQL 表(例如jobs)。每个工人的任务是:

  1. 找到最老的QUEUED工作
  2. 将其状态设置为RUNNING
  3. 返回对应的ID。

请注意,当工作人员运行步骤 #1 时,可能存在任何合格(即)作业。QUEUED

到目前为止我有以下伪代码。ROLLBACK我相信如果步骤 #1 没有返回作业,我需要取消 ( ) 交易。我将如何在下面的代码中做到这一点?

BEGIN TRANSACTION;

# Update the status of jobs fetched by this query:
SELECT id from jobs WHERE status = "QUEUED" 
ORDER BY created_at ASC LIMIT 1;

# Do the actual update, otherwise abort (i.e. ROLLBACK?)
UPDATE jobs
SET status="RUNNING"
# HERE: Not sure how to make this conditional on the previous ID
# WHERE id = <ID from the previous SELECT>

COMMIT;
Run Code Online (Sandbox Code Playgroud)

Bil*_*win 3

本周我正在实施与您的案例非常相似的事情。多个工作人员,每个人都抓住一组行中的“下一行”进行工作。

伪代码是这样的:

BEGIN;

SELECT ID INTO @id FROM mytable WHERE status = 'QUEUED' LIMIT 1 FOR UPDATE;

UPDATE mytable SET status = 'RUNNING' WHERE id = @id;

COMMIT;
Run Code Online (Sandbox Code Playgroud)

使用FOR UPDATE对于避免竞争条件很重要,即多个工人试图抢同一行。

有关 的信息,请参阅https://dev.mysql.com/doc/refman/8.0/en/select-into.htmlSELECT ... INTO