PHP/MySQL中的任务队列:竞争条件

PHP/MySQL中的任务队列:竞争条件,php,mysql,queue,conditional-statements,race-condition,Php,Mysql,Queue,Conditional Statements,Race Condition,我正在用PHP实现一个脱机任务队列。联机页在此表中插入记录以安排工作: create table sl_task_queue ( task_id int primary key auto_increment, task_data varchar(255) not null, started_date datetime, completed_date datetime, priority int not null default 10 ) ENGINE=In

我正在用PHP实现一个脱机任务队列。联机页在此表中插入记录以安排工作:

create table sl_task_queue (
    task_id int primary key auto_increment,
    task_data varchar(255) not null,
    started_date datetime,
    completed_date datetime,
    priority int not null default 10
) ENGINE=Innodb;
然后,离线时,我有一个PHP CLI进程池,它们处于循环中,等待工作完成。要查询工作,他们运行以下功能:

$SEMKey = "849039";
$seg = sem_get( $SEMKey, 2, 0666, -1) ; 

function getTask() {
    sem_acquire($GLOBALS['seg']);

    // This function returns null for no results, or a Task ORM object on success
    $Task = eSqlObject("Task", "select * from sl_task_queue 
        where started_date is null 
        order by task_id asc limit 1 for update"); 

    if( $Task ) {
        // Set started_date to claim this task
        $Task = new LucidityTask($hash);
        $Task['started_date'] = date("Ymd H:i:s");
        $Task->save(); // performs an UPDATE query
    }

    sem_release($GLOBALS['seg']);   

    return $Task;
}
我在这里尝试了两件事,一个PHP信号和MySQL的“选择…更新”特性。我还尝试了一个完全锁表命令。尽管如此,守护进程中声明同一行的两个进程仍然存在问题,我无法确定原因。有两个疑问-当您执行单独的CLI进程时,PHP的信号量是否会进入derp模式?或者MySQL真的花了很多时间来更新底层表数据,这样在这个函数退出后,SELECT查询仍然会在短时间内返回旧数据吗

还有其他想法吗


非常感谢

GAH!这就是为什么复制/粘贴是邪恶的。问题是:

$seg = sem_get( $SEMKey, 2, 0666, -1) ; 

“2”允许两个进程同时获取信号量。谢谢你,路易斯·H

添加其他字段…例如uniqueID

1) 生成唯一ID

$uniqueID = uniqid();
2) 更新一行。设置字段uniqueID=$uniqueID

3) 选择一行,其中uniqueID=$uniqueID 如果行存在->执行作业其他->尝试标记/获取另一条记录

4) 删除作业完成时uniqueID=$uniqueID的行

利润!:)

此外,您还可以设置“endTime”=currentDateTime+N_分钟(分钟-此行将被锁定的时间)
当endTime但您打算一次最多执行2个进程时,请清除uniqueID?池大小取决于要执行的工作量。现在我已经将它设置为一次最多运行40个进程,所以这需要很好地处理并发性。现在它可以工作了吗?很高兴我能为你指出正确的方向。嘿,你的评论触发了灯泡。非常感谢!