2010-03-13 78 views
3

我開發了一個基於AJAX的遊戲,其中存在一個錯誤(非常偏遠,但在數量上至少每小時發生一次),由於某種原因,兩個請求幾乎同時發送到處理頁面(我跟蹤的最後一個,請求相差0.0001毫秒)。在執行查詢之前有一個檢查,以確保它不會被執行兩次,但由於差異非常小,在執行下一個查詢之前該檢查尚未完成。我很難過,因爲它在遊戲中造成了嚴重的問題,所以我怎麼能夠阻止它呢?停止2個幾乎同時執行的相同查詢?

爲了更清楚起見,查詢在遊戲中開始新一輪,所以當它執行兩次時,它會在打破遊戲的同時開始2輪,所以我需要能夠停止腳本如果前一輪沒有結束,即使前一輪開始.0001毫秒前。

回答

3

訣竅是使用原子更新語句來做兩件事都不能成功的事情。他們不能都成功,所以你可以簡單地做一個查詢,如:

UPDATE gameinfo SET round=round+1 WHERE round=1234 

其中1234是本輪這是正在進行中。然後檢查受影響的行數。如果線程影響零行,則失敗並且其他人在事先做好了。我假設上面的代碼將在自己的事務中執行,就像自動提交一樣。

1

所以你真正需要的是一個應用程序廣泛的互斥體。 flock()sem_acquire()提供了這一點 - 但僅在系統級別 - 如果應用程序分佈在多個服務器上,則需要使用memcached或實現自己的套接字服務器來協調節點。

或者,您可以使用數據庫作爲公共存儲區 - 例如,與MySQL獲得一張桌子上的鎖,檢查輪最後開始時,如果有必要更新行說,新一輪開始(並記住這一點 - 然後解鎖表。 。

0

鎖是這樣做的一個辦法,但在某些情況下,一個簡單的方法就是讓你的要求冪等。這只是意味着調用它一再具有完全一樣調用一次的效果相同。

例如,您的電話此刻有效確實$round++;明顯反覆打電話會造成麻煩

但是你可以做$round=$newround;這裏重複的呼叫不會有任何效果,因爲輪已經被設置,而第二次呼叫只是將其設置爲相同的值。

相關問題