PHP,mysqli和表锁?

时间:2009-10-16 19:35:48

标签: php mysqli locking

我有一个数据库表,我需要拉一行,测试匹配的用户输入,然后更新行以识别进行匹配的用户。如果出现竞争条件,我需要确保第一个用户的更新不会被其他用户覆盖。

要做到这一点,我打算:
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连接,用于在数据库上执行预准备语句。

当我运行我的测试脚本时,我启动第一个用户并等待“Stalling to allow for conflict ...”,然后启动第二个脚本。在第二个脚本我希望它阻止“锁定...”,然而,第二个脚本也继续“Stalling以允许冲突......”。

由于LOCK声明似乎没有阻塞,也没有返回获取锁定的任何指示(返回值被回显和空白),我不清楚我实际上正在获取锁定。即使我,我也不确定如何继续。

任何指针?

1 个答案:

答案 0 :(得分:3)

故障排除:您可以尝试使用另一个未锁定的表来测试表锁定是否成功。如果您获得了锁,则尝试写入未包含在lock语句中的表应该会生成错误。

您可能需要考虑替代解决方案。而不是锁定,执行包含更改的元素的更新作为where子句的一部分。如果您正在更改的数据在读取后发生了更改,则更新将“失败”并返回零行修改。这消除了表锁,以及可能带来的所有混乱恐怖,包括死锁。