如何同步mysql数据库请求?

时间:2011-02-16 16:30:49

标签: php mysql multithreading synchronization acid

我在表中有很多条目用于执行作业。这可以扩展到几台服务器。

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

我目前通过在表中更新一个名为“jobserver”的字段来执行此操作,该字段默认为null,并带有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交易。

所以我可以执行select和update as one。但这看起来和工作怎么样?

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

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

  • 一般是理智吗?你会采用不同的方式吗?

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

2 个答案:

答案 0 :(得分:2)

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

答案 1 :(得分: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
");