防止在 mySQL 中选择同一行

Prevent same row being selected in mySQL

我接到了创建 "Mass Crawler" 的任务,它完全依赖于数据库中的代理。这是我试图实现的目标的简单概述:

我已经查看了 TRANSACTIONS 和 mySQL,但我仍然认为这样做无济于事,因为查询将在同一时间对每个人执行爬虫进程。

这是我脑海中关于单个爬虫文件的想法:

$db = new MysqliDb("localhost", "username", "password", "database");

$db->connect();
$db->startTransaction();
$db->where("last_used", array("<" => "DATE_SUB(NOW(),INTERVAL 30 SECOND)"));
$proxies = $db->get("proxies", 1);
if(count($proxies) == 1) {

    //complete any scraping that needs to be done

    //update the database to say the proxy has just been used
    $db->where("id", $accounts[0]['id']);
    $db->update("proxies", array("last_used", date("Y-m-d H:i:s")));

    //commit the complete transaction
    $db->commit();
}
$db->disconnect();

上面的示例是否是使用 mySQL TRANSACTION 功能并确保 ALL 并行查询选择不同行的正确方法?

您需要 table 中的一列来指示该行正在被其中一个搜寻器进程使用。您的第一个 SELECT 应该寻找 WHERE in_use = 0;不过,它需要使用 FOR UPDATE 子句来锁定已处理的行。

SELECT *
FROM proxies
WHERE in_use = 0
LIMIT 1
FOR UPDATE;

我不知道如何使用您正在使用的数据库 API 编写该查询;您可能需要使用它的功能来执行原始查询。

然后将该行更新为 SET in_use = 1。通过在一个事务中执行这两个操作,您可以确保没有其他进程会获取该行。

处理完该行后,它可以 SET in_use = 0