我需要运行一个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();
}
是否有可能同时运行两个脚本?
答案 0 :(得分:0)
不,他们不能同时运行,here's MySQL关于UPDATE
和SELECT
的文档,这就是它所说的:
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,都是一样的。