防止在 mySQL 中选择同一行
Prevent same row being selected in mySQL
我接到了创建 "Mass Crawler" 的任务,它完全依赖于数据库中的代理。这是我试图实现的目标的简单概述:
- 1 x CronJob Bootstrap 文件 - 这是向 单个爬虫 文件发送 50 个并行 curl 请求的文件
- 1 x Individual Crawler 文件 - 这应该从数据库中获取另一个进程未选择的 UNIQUE 行(代理)。
我已经查看了 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
。
我接到了创建 "Mass Crawler" 的任务,它完全依赖于数据库中的代理。这是我试图实现的目标的简单概述:
- 1 x CronJob Bootstrap 文件 - 这是向 单个爬虫 文件发送 50 个并行 curl 请求的文件
- 1 x Individual Crawler 文件 - 这应该从数据库中获取另一个进程未选择的 UNIQUE 行(代理)。
我已经查看了 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
。