1

我在一个表中有很多条目是为了执行工作而提取的。这可以扩展到多台服务器。

当服务器获取一堆行以添加到自己的作业队列中时,它们应该被“锁定”,以便没有其他服务器获取它们。当执行更新时,时间戳会增加并且它们被“解锁”。

我目前通过更新表中名为“jobserver”的字段来执行此操作,该字段默认为空,并带有作业服务器的 id。

作业服务器仅选择字段为空的行。

当所有行都被处理时,它们的时间戳被更新,最后作业字段再次设置为空。

所以我需要同步这个:

$jobs = mysql_query("
SELECT itemId 
FROM items 
WHERE 
jobserver IS NULL 
AND 
DATE_ADD(updated_at, INTERVAL 1 DAY) < NOW()
LIMIT 100
");

mysql_query("UPDATE items SET jobserver = 'current_job_server' WHERE itemId IN (".join(',',mysql_fetch_assoc($jobs)).")");

// do the update process in foreach loop
// update updated_at for each item and set jobserver to null

每个服务器都在无限循环中执行上述操作。如果没有返回任何字段,则所有内容都是最新的 2 日期(最后一次更新不超过 24 小时)并被发送到 10 分钟。

我目前有 MyIsam,我想继续使用它,因为在我的情况下,它的性能比 innodb 好得多,但我听说 innodb 有 ACID 事务。

所以我可以执行选择并更新为一个。但这看起来和工作如何?

问题是我无法锁定表或其他东西,因为其他进程需要读/写并且无法锁定。

我也对共享信号量等更高级别的解决方案持开放态度。问题是同步需要跨多个服务器。

  • 这种方法通常是理智的吗?你会做不同的事吗?

  • 如何同步作业 selectino 以确保两台服务器不会更新相同的行?

4

2 回答 2

2

您可以先运行 UPDATE,但要使用 SELECT 上的 WHERE 和 LIMIT。然后,您选择将 jobserver 字段设置为您的服务器的行。

于 2011-02-16T16:44:28.080 回答
1

如果您不能锁定表,那么我会以未修改的行为条件进行更新。就像是:

$timestamp = mysql_query("SELECT DATE_SUB(NOW(), INTERVAL 1 DAY)");

$jobs = mysql_query("
SELECT itemId 
FROM items 
WHERE 
jobserver IS NULL 
AND 
updated_at < ".$timestamp."
LIMIT 100
");

// Update only those which haven't been updated in the meantime
mysql_query("UPDATE items SET jobserver = 'current_job_server' WHERE itemId IN (".join(',',mysql_fetch_assoc($jobs)).") AND updated_at < ".$timestamp);

// Now get a list of jobs which were updated
$actual_jobs_to_do = mysql_query("
SELECT itemId
FROM items
WHERE jobserver = 'current_job_server'
");

// Continue processing, with the actual list of jobs

您甚至可以组合选择和更新查询,如下所示:

mysql_query("
UPDATE items
SET jobserver = 'current_job_server'
WHERE jobserver IS NULL
AND updated_at < ".$timestamp."
LIMIT 100
");
于 2011-02-16T16:44:47.547 回答