2011-02-16 136 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 
");