2011-03-07 45 views
2

問:如何在沒有PHP Semaphore的PHP中實現信號量?

我怎樣才能實現共享內存變量在PHP沒有信號包(http://php.net/manual/en/function.shm-get-var.php)?

語境

  • 我有一個簡單的Web應用程序(實際上爲WordPress插件)
  • 這得到一個URL
  • 這則檢查數據庫,如果該網址已經存在
  • 如果不是然後它出去,並做了一些操作
  • ,然後將該記錄寫入數據庫,並將url作爲唯一條目

實際情況是,4,5,6 ...會話同時請求url,並且我在url的數據庫中獲得了9個重複條目..(可能9是因爲處理時間並且第一個條目的數據庫寫入只需要足夠的時間讓其他9個請求通過)。之後,所有的請求都會讀取記錄已經存在的正確條目,這樣做很好。

由於它是一個WordPress插件,因此將有許多用戶在各種共享主機平臺上使用PHP的可變編譯/設置。

所以我正在尋找更通用的解決方案。我不能使用數據庫或文本文件寫入,因爲這些會太慢。當我寫入數據庫時​​,下一個會話將已經通過。

供參考:數據庫代碼:http://plugins.svn.wordpress.org/wp-favicons/trunk/includes/server/plugins/metadata_favicon/inc/class-favicon.php

更新

一起使用的URI的一個新的MD5哈希的唯一密鑰與試捕撈周圍似乎工作。

我發現

SELECT uri, COUNT(uri) AS NumOccurrences 
FROM edl40_21_wpfavicons_1 
GROUP BY uri 
HAVING (
COUNT(uri) >1 
) 
LIMIT 0 , 30 

所以1個重複條目我認爲它沒有工作,但這是因爲他們是:

http://en.wikipedia.org/wiki/Book_of_the_dead 
http://en.wikipedia.org/wiki/Book_of_the_Dead 

(首都GRIN)

回答

3

這可以通過MySQL來實現。

您可以通過鎖定表讀取權限來明確地執行此操作。這將阻止對整個表的任何讀取訪問,所以可能不是優選的。 http://dev.mysql.com/doc/refman/5.5/en/lock-tables.html

否則,如果在表中的字段被列爲唯一的,那麼在下次會議上試圖寫入同一個URL表,他們會得到一個錯誤,你可以捕捉這個錯誤並繼續,因爲沒有必要做如果條目已經在那裏,任何東西。浪費的唯一時間是兩個或更多會話創建相同URL的可能性,結果仍然是一條記錄,因爲數據庫不會再次添加相同的唯一URL。

正如評論中所述,由於URL的長度可能很長,並且固定長度的唯一散列可以幫助解決該問題。

+0

這是一個額外的存儲大,但也許你可以使用一個獨特的哈希來代替? – Jacob 2011-03-08 00:14:21

+0

鎖定整個表有點苛刻,在1鎖期間,我可能有N個進程無法寫入(來自不同的uris)。不能使uri具有唯一性:唯一字段有最大長度。一個獨特的散列很有趣,也許這也是美味。在這裏你看到混合數據庫請求:http://leau.co/wp-content/blogs.dir/21/files/wp-favicons/cache/DEBUG.LOG – edelwater 2011-03-08 00:16:35

+0

因爲我不知道是否存在uri記錄它可能會像這樣(A)更新記錄中的LOCK其中uri_hash = md5(uri)try catch(B)如果存在則讀取(C)如果存在release A(D)如果不存在則執行處理,寫入和釋放A - :) – edelwater 2011-03-08 00:21:44

1

還有其他的共享PHP中的內存模塊(例如shmopAPC),但我認爲你所說的是有一個問題依賴於非標準/不是p重新安裝庫。

我的建議是,在你去做「其他操作」之前,你需要在數據庫中輸入一個條目,可能是「編譯」狀態(或某些東西),所以你知道它仍然不可用。這樣,您就不會遇到獲取多個條目的問題。我也可以確定你使用的事務是可用的,所以你的提交是原子的。

然後,當你的「其他行動」完成後,更新數據庫條目「可用」,並做到這一點是其他任何你需要做的。