如何使用mysql数据库管理单线程作业?

时间:2017-05-03 18:58:43

标签: mysql single-threaded

我需要运行一个php脚本,我想确保同时运行的脚本不超过一个。

我正在使用mysql,我想解决这个问题:

我构建了轰鸣声数据库:

       job_id              |  task_id | last_updated_time (AUTO UPDATE)
  "sending_emails"              77238      2107-5-3 12:2:2

在运行脚本之前,我创建随机任务ID,然后运行查询以更新task_id。

 $task_id = generate_random_task_id();
    $query = "
                  UPDATE  
                         jobs  
                   SET
                         task_id = $task_id
                   WHERE
                        task_id = $task_id
                        OR
                        NOW() - last_updated_time > 30
                   LIMIT 1
             "

/*
  Then I need to check if there was an update, if yes then I will run the script otherwise i will stop since there is already another script running
*/

$query = "SELECT JOB_ID WHERE taks_id = $task_id "
$result = run($query)
if( ! isset($result[JOB_ID])){
    DIE();
}

是否有可能同时运行两个脚本?

3 个答案:

答案 0 :(得分:0)

不,他们不能同时运行,here's MySQL关于UPDATESELECT的文档,这就是它所说的:

  

UPDATE ... WHERE ...在每条记录上设置一个独占的下一键锁定   搜索遭遇。但是,只需要索引记录锁定   对于使用唯一索引锁定行以搜索a的语句   独特的一行。

Here's有关共享和独占锁定的更多信息:

  

共享(S)锁允许持有锁的事务读取   一排。

     

独占(X)锁允许持有锁的事务   更新或删除一行。

     

如果事务T1在行r上持有独占(X)锁,则为请求   从某个不同的事务T2中获取r上任一类型的锁   不能立即授予。相反,事务T2必须等待   事务T1释放其对行r的锁定。

答案 1 :(得分:0)

是的,您有机会再次执行相同的任务。

有两个明显的解决方案。

一个是打开一个mysql连接然后使用GET_LOCK()使用短暂超时获取一个锁 - 如果你获得了锁,那么你就可以了。您需要在脚本的生命周期内维护数据库连接。

或者你可以在finish_time上创建一个具有唯一约束的表,INSERT一个带有空结束时间的记录来指示开始(如果已经有一个具有空完成时间的记录,它将失败)然后将finish_time更新为NOW ()完成时。

但是,当任务在一个无法耦合但高度可用的集群中运行时,使用数据库来表示正在运行的任务的状态才有意义 - 这意味着数据库也是集群的。集群的性质(NDB,asych,半同步,多主机)对它在实践中的表现有很大的影响。

OTOH如果不是这样,那么使用数据库来表示状态是解决问题的错误方法。

答案 2 :(得分:0)

是的,它们可以同时运行。 如果您希望他们一次运行一个SELECT 查询应更改为:

SELECT JOB_ID WHERE taks_id = $task_id LOCK IN SHARED MODE

在这种情况下,它使用读锁定。

无论您使用的是NDB还是InnoDB,都是一样的。