首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >mysqli和表锁?

mysqli和表锁?
EN

Stack Overflow用户
提问于 2009-10-16 19:35:48
回答 1查看 4.9K关注 0票数 2

我有一个数据库表,我需要在其中提取一行,测试用户输入是否匹配,然后更新该行以识别进行匹配的用户。如果出现争用情况,我需要确保第一个用户的更新不会被另一个用户覆盖。

为了实现这一目标,我打算:

  1. Read row
  2. Lock table
  3. Read row,如果行与update匹配,则再次读取行并与原始行进行比较
  4. ,否则不执行任何操作(其他用户已更新行)

根据我在Google上找到的信息,我预计lock table语句会阻塞,直到获得锁为止。我在PHP中设置了一个小测试脚本,该脚本将暂停10秒,以便有时间手动创建竞态条件。

代码语言:javascript
复制
 // 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";
}

其中,锁例程定义为

代码语言:javascript
复制
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语句看起来没有阻塞,也没有返回任何获取锁的指示符(返回值是回显的且为空),所以我不清楚我实际上是不是在获取锁。即使我是,我也不确定该怎么做。

有什么建议吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2009-10-17 06:43:21

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

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

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1579995

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档