我有一個數據庫表,我需要拉一行,測試用戶輸入的匹配,然後更新行來標識匹配的用戶。如果出現競爭狀況,我需要確保第一位用戶的更新不會被其他用戶覆蓋。PHP,mysqli和表鎖?
要做到這一點,我打算:
1.逐行讀取
2.鎖定表再次
3.閱讀行,並比較原始行
4.如果相匹配的行更新,否則什麼也不做(另一個用戶已經更新了該行)
根據我在Google上找到的信息,我預計鎖表語句會阻塞,直到獲得鎖。我在PHP中設置了一個小測試腳本,它會停頓10秒,以便我有時間手動創建競爭條件。
// attempt to increment the victor number
$aData["round_id"] = $DATABASE["round_id"];
// routine to execute a SELECT on database (ommited for brevity)
$aRound = $oRound->getInfo($aData);
echo "Initial Round Data:";
print_r($aRound);
echo "Locking...";
echo $oRound->lock();
echo "Stalling to allow for conflict...";
sleep(10);
echo "Awake...";
$aLockedRound = $oRound->getInfo($aData);
if($aRound["victor_nation"] == $aLockedRound["victor_nation"]){
$aData["victor_nation"] = $aRound["victor_nation"] + 1;
$oRound->update($aData);
echo "Incremented Victor Nation";
}
在鎖定常規定義爲
function lock(){
global $oDatabase;
$iReturn = 0;
// lock the table
$iReturn = $oDatabase->m_oConnection->query("LOCK TABLES round WRITE");
return $iReturn;
}
以上,$oDatabase->m_oConnection
的是,我用它來在數據庫上執行準備語句的mysqli的連接。
當我運行我的測試腳本時,我啓動第一個用戶並等待「停頓以允許衝突...」,然後啓動第二個腳本。關於第二個腳本,我希望它阻止在「鎖定...」,但是,第二個腳本也繼續「停頓以允許衝突......」。由於LOCK陳述似乎沒有被阻塞,也沒有返回獲取鎖的任何指示器(返回值被回顯並且空白),所以我不清楚我是否實際上獲取了鎖。即使我是,我不知道如何繼續。
任何指針?
Innodb或MyIsam表? – 2009-10-16 20:15:19
該表是MyIsam – 2009-10-20 00:42:57