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

如何使用mysql数据库管理单线程作业?,mysql,single-threaded,Mysql,Single Threaded,我需要运行一个php脚本,我想确保在同一时间运行的脚本不超过一个 我使用的是mysql,我想到了这个解决方案: 我建立了以下数据库: job_id | task_id | last_updated_time (AUTO UPDATE) "sending_emails" 77238 2107-5-3 12:2:2 在运行脚本之前,我创建了随机任务id,然后运行查询来更新任务id $task_id = genera

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

我使用的是mysql,我想到了这个解决方案:

我建立了以下数据库:

       job_id              |  task_id | last_updated_time (AUTO UPDATE)
  "sending_emails"              77238      2107-5-3 12:2:2
在运行脚本之前,我创建了随机任务id,然后运行查询来更新任务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();
}

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

不,它们不能同时运行,MySQL关于
更新
选择
的文档,它是这样说的:

更新。。。哪里在每条记录上设置独占的下一个密钥锁 搜索遭遇。但是,只需要索引记录锁 对于使用唯一索引锁定行以搜索 唯一行

有关共享锁和独占锁的详细信息:

共享锁允许持有锁的事务读取 一排

独占(X)锁允许将锁保存到的事务 更新或删除一行

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


是的,您完全有可能再次运行相同的任务

有两个显而易见的解决方案

一种是打开一个mysql连接,然后使用一个短的超时获取一个锁——如果您获得了锁,那么您就可以开始了。您需要在脚本的生命周期内维护db连接

或者,您可以创建一个表,在finish_time上使用一个唯一的contint,插入一个finish_time为null的记录以指示开始(如果已经有一个finish_time为null的记录,则将失败),然后在完成时更新finish_time to NOW()

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


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

是的,它们可以同时运行。 如果希望它们一次运行一个
选择

查询应更改为:

SELECT JOB_ID WHERE taks_id = $task_id LOCK IN SHARED MODE
在这种情况下,它使用读取锁


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

谢谢您的回答,但我不确定为什么“完成时间”会起作用,而我的不起作用?请您看看@Darshan Mehta答案!撇开在SQL中按时进行计算而不指定时间间隔的复杂性不谈,只有在保证执行时间不超过30秒的情况下,您的目标才能实现。根据数据库中的并发模型,还会出现竞争条件。此外,在您的示例中,您的任务id生成的熵非常低-如果您以较高的频率运行此任务,您将在某个点上遇到冲突。我需要继续吗?