如何处理mysql的多线程请求以获得空闲行?

时间:2015-05-30 12:52:27

标签: mysql multithreading

假设您有一个由100k个作业组成的表,每个作业都需要处理。

job_id (int)
job_details (whatever)
job_status (Enum: Not processed, Processing, Processed)

我的核心软件,例如有100个线程处理这些作业,所以每个线程都需要一个工作来处理,它获得一个免费的工作,因此它查询未处理工作,将其标记为处理,完成后将其标记为已处理

问题是当100个线程开始工作时,因为许多线程在查询Select * from jobs where job_status='Not processed' limit 1 update jobs set job_status='processing' where job_id=%JOB_ID%时会一起开始,因为很多线程都要处理相同的工作!这是非常错误的。

我该如何正确地做到这一点?

1 个答案:

答案 0 :(得分:1)

如果jobs是InnoDB表,那么您可以在事务中使用SELECT ... FOR UPDATE来分配单个作业:

BEGIN
SELECT * FROM jobs WHERE job_status = 'Not processed' LIMIT 1 FOR UPDATE
UPDATE jobs SET job_status = 'Processing' WHERE job_id = ?
COMMIT

指定FOR UPDATE锁定所选行。同时执行SELECT查询的单独事务(线程)将等待第一个事务完成。

或者,如果您修改jobs表以记录已为该任务分配的线程,则可以在没有事务的情况下执行分配。首先,分配一个作业,将作业的owner_thread属性设置为某个对执行线程唯一的标识符:

UPDATE jobs 
   SET job_status = 'Processing', owner_thread = ? 
 WHERE job_status = 'Not processed'
 LIMIT 1

然后使用执行线程的唯一标识符检索已分配的作业的详细信息:

SELECT job_id, job_details FROM jobs WHERE owner_thread = ?