php - 并行 cron 作业选取相同的 SQL 行

标签 php mysql sql cron

我基本上有一个 cron 文件,它在 cron 文件内同时向 1 个文件发送 multi_curl ,因此是并行的。

我的cron文件如下所示(发送并行请求)

<?php
require "files/bootstrap.php";
$amount = array(
    "10","11","12","13","14"
);
$urls = array();
foreach($amount as $cron_id) {
    $urls[] = Config::$site_url."single_cron.php?cron_id=".$cron_id;
}
$pg = new ParallelGet($urls);
?>

然后在我的 single_cron.php 中我得到以下查询

SELECT * 
  FROM accounts C JOIN proxies P 
                    ON C.proxy_id = P.proxy_id 
 WHERE C.last_used < DATE_SUB(NOW(), INTERVAL 1 MINUTE)
   AND C.status = 1
   AND C.running = 0
   AND P.proxy_status = 1
   AND C.test_account = 0
 ORDER BY uuid() 
 LIMIT 1

即使我在查询中获得了uuid,它们似乎仍然以某种方式拾取同一行,防止这种情况的最佳方法是什么?我听说过一些关于交易

的事情

我当前使用的框架是 PHP,因此如果其中有任何解决方案可行,那么我可以自由选择解决方案。

最佳答案

检查select for update命令。这可以通过阻止其他并行查询来选择同一行,直到您执行 commit 。因此,您的选择应包含一些条件,例如 last_process_time > 60 ,您应该在选择该行后更新该行,并将 last_processed_time 设置为当前时间。也许您有不同的机制来检测最近是否选择/处理了一行,您也可以使用它。重要的是select for update将会在行上放置一个锁,因此即使您并行运行查询,它们也会被 mysql 服务器序列化。

这是确保您没有 2 个查询选择同一行的唯一方法 - 即使您通过 uuid() 进行的订单工作正常,您还是会时不时地在 2 个并行查询中选择同一行.

使用事务执行此操作的正确方法是:

START TRANSACTION;

SELECT * 
    FROM accounts C JOIN proxies P 
                ON C.proxy_id = P.proxy_id 
    WHERE C.last_used < DATE_SUB(NOW(), INTERVAL 1 MINUTE)
    AND C.status = 1
    AND C.running = 0
    AND P.proxy_status = 1
    AND C.test_account = 0
    LIMIT 1;

(假设您的帐户表中有一个“ID”列用于唯一标识行)

UPDATE accounts
set last_used=now(), .... whatever else ....
where id=<insert the id you selected here>;

COMMIT;

将执行最先到达服务器的查询,并锁定返回的行。此时所有其他查询都将被阻止。现在您可以更新任何您想要的内容。提交后,来自其他进程的其他查询将被执行。他们不会找到您刚刚更改的行,因为 last_used < ...条件不再成立。其中一个查询将找到一行,锁定它,其他查询将再次被阻止,直到第二个进程执行提交。这一直持续到一切都完成。

而不是 START TRANSACTION ,您也可以在 session 中将 autocommit 设置为 0。并且不要忘记这仅在您使用 InnoDB 表时才有效。如果您需要更多详细信息,请查看我给您的链接。

关于php - 并行 cron 作业选取相同的 SQL 行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20799844/

相关文章:

php - 嵌套的php循环仅在连接到sql时运行一次

php - 在 mysql 中附加以逗号分隔的字符串时出现语法错误

php - 要列出的其他表格

PHP - 嵌套递归 SQL 查询不检索值

php - 删除上传到mysql数据库的csv文件中的第一行

mysql - 根据另一个表中的值更新一个表中的 MySQL 行

c# - 使用 SQL (SDF) 数据库中的项填充 WPF 列表框

php mysql 查询表中最后设置的行数

php - 喜欢一个帖子的按钮实际上喜欢所有帖子

php - PHP 在不同操作系统下的微秒精度是多少?