我有一个PHP脚本,从数据库检索行,然后根据内容执行工作。 这项工作可能很耗时(但不一定是计算高昂的),因此我需要允许多个脚本并行运行。
数据库中的行大致如下:
+---------------------+---------------+------+-----+---------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------------+---------------+------+-----+---------------------+----------------+
| id | bigint(11) | NO | PRI | NULL | auto_increment |
.....
| date_update_started | datetime | NO | | 0000-00-00 00:00:00 | |
| date_last_updated | datetime | NO | | 0000-00-00 00:00:00 | |
+---------------------+---------------+------+-----+---------------------+----------------+
我的脚本目前选择最旧的日期在date_last_updated
中的行(一旦完成工作就会更新),并且不使用date_update_started
。
如果我现在同时运行多个脚本实例,它们将选择相同的行(至少有些时间)并且会重复执行工作。
我想做的是使用事务来选择行,更新date_update_started
列,然后向选择行的SQL语句添加一个WHERE
条件,只选择具有date_update_started
大于某个值的行(以确保另一个脚本没有在处理它)。例如:
$sth = $dbh->prepare('
START TRANSACTION;
SELECT * FROM table WHERE date_update_started > 1 DAY ORDER BY date_last_updated LIMIT 1000;
UPDATE table DAY SET date_update_started = UTC_TIMESTAMP() WHERE id IN (SELECT id FROM table WHERE date_update_started > 1 DAY ORDER BY date_last_updated LIMIT 1000;);
COMMIT;
');
$sth->execute(); // in real code some values will be bound
$rows = $sth->fetchAll(PDO::FETCH_ASSOC);
根据我所了解的,这本质上是队列实现方式,在MySQL中似乎不被看好。尽管如此,我仍然需要找到一种允许多个脚本并行运行的方法,而在我所做的研究中,这就是我想出来的方案。
这种方法会有效吗?是否有更好的方法?
SELECT ... LIMIT 5
),然后为每个行启动一个单独的处理脚本实例。您甚至可以使用第二个表来跟踪当前运行的处理实例数量,因此每当 cron 启动您的主脚本时,它都会知道要获取多少行。但由于这与您所要求的完全不同,因此我决定将其作为评论而不是答案添加。 - Patrick Echterbruch