Php 使用表锁(MySQL)防止并行执行
我有一个名为cronjobs的MySQL表,它保存了每个cronjob所需的entires(例如,删除旧电子邮件、更新配置文件年龄等)。对于每个cronjob,都有一个定义的代码块,如果cronjob到期,就会执行该代码块(对于不同的cronjob,我得到了不同的间隔) 对于due-cronjobs的执行,我得到了一个PHP脚本,它每分钟由UNIX crontab执行一次(调用execute\u cronjobs\u due.sh,它调用“PHP-f/path/to/file/execute\u cronjobs\u due.PHP”) 在执行execute_cronjobs_due.php时,所有cronjobs都会被标记为将要执行,这样,对execute_cronjobs_due.php的另一个调用不会导致已经执行的同一个cronjob的并行执行 现在的问题是:有时执行时间超过60秒,但crontab程序在这60秒后不会调用execute_cronjobs_due.sh。实际发生的情况是,在执行前一个crontab之后立即调用execute_cronjobs_due.sh。如果一次执行需要120秒以上,那么接下来的两次执行将同时初始化 时间线: 2015-06-15 10:00:00:执行执行cronjobs.sh(需要140秒) 2015-06-15 10:02:20:execute_cronjobs_due.sh的两次同时执行 因为它是完全同时执行的,所以没有必要将cronjob标记为它们正在执行,因为选择(实际上应该排除标记的一次)是在完全相同的时间执行的。因此,更新发生在两个作业都已选择到期的作业之后 如何解决这个问题,使cronjobs不会同时执行?我可以使用MySQL表锁吗 非常感谢您事先的帮助Php 使用表锁(MySQL)防止并行执行,php,mysql,cron,table-locking,table-lock,Php,Mysql,Cron,Table Locking,Table Lock,我有一个名为cronjobs的MySQL表,它保存了每个cronjob所需的entires(例如,删除旧电子邮件、更新配置文件年龄等)。对于每个cronjob,都有一个定义的代码块,如果cronjob到期,就会执行该代码块(对于不同的cronjob,我得到了不同的间隔) 对于due-cronjobs的执行,我得到了一个PHP脚本,它每分钟由UNIX crontab执行一次(调用execute\u cronjobs\u due.sh,它调用“PHP-f/path/to/file/execute\u
Frederic是的,您可以使用mysql表锁,但对于您的情况来说,这可能有些过头了。不管怎么说,我想用最普通的方式来做
getmypid()
)或主机+pid的组合。或者,如果您不知道哪一个是完美的,只需生成guid即可UPDATE cronjobs SET executed\u by=my\u id,其中executed\u by为null,并且/*无论什么条件都可以让作业运行*/
从cronjobs中选择*,其中执行者=my\u pid
UPDATE cronjobs set executed\u by=null,其中executed\u by=my\u pid
SET executed_by=my_id,start_at=NOW(),其中executed_by为null或(executed_by不为null,start_at
)
如何解决这个问题,使cronjobs不会同时执行
有多种方法可以解决此问题。它们也可能有帮助:
我的建议是保持简单,使用文件锁定或文件存在检查方法
- 文件_exist()+基于PID的CronHelper类
- flock()基于:
- 如果要避免IO,请将锁定状态存储到memcache中
- 数据库事务:见下文和@sakfa的答案
- 使用Redis作为中心锁定分布式系统中的cronjobs:&
这确保了“从Todo中选择作业”和“将其标记为正在运行/已启动”只需一步即可完成。最后,您可能仍然拥有“central cronjob processing script”的多个exec,但不会多次选择要处理的作业。您使用的cron不是按照请求的计划执行作业,而是等待其他作业完成?