2011-02-16 123 views
1

我在表中有很多条目被提取用于执行作业。这是缩放到几个服务器。如何同步mysql数据库请求?

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

我目前通过更新表中名为“jobserver”的字段来执行此操作,该表中缺省为jobserver的id为null。

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

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

,所以我需要同步的:

$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以确保两台服务器不更新相同的行?

回答

2

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

+0

好主意!但它确保同步?我的意思是。如果更新需要一些时间并且与此同时另一个进程想要更新呢?是甚至在myisam中的一个查询原子? – 2011-02-16 16:49:38

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 
");