php - MySQL UPDATE 语句未按预期锁定行

标签 php mysql locking

我有一个表,其中每一行代表可供消费者使用的资源。该资源在任何时候只能由一个消费者使用。消费者选择可用资源并随机选择一个。为了确保消费者可以使用它选择的资源,我有以下 SQL 语句: UPDATE resource SET is_in_use=1 WHERE is_in_use=0 AND id=?

如果受影响的行数 = 1,我认为这意味着消费者拥有该资源的独占使用权。并非如此。我偶尔会遇到将多个消费者分配给单个资源的情况。

完整的 php 代码:

public function useResource() {
    $mysqli = secureMysqli();
    if ($stmt = $mysqli->prepare("UPDATE resource SET is_in_use=1 WHERE is_in_use=0 AND id=?")) {
        $stmt->bind_param('i', $this->id);
        if($stmt->execute())
        {
            if($mysqli->affected_rows == 1) {
                return true;
            } else {
                return false;
            }
        } else {
            return false;
        }
   }
   return false;
}

最佳答案

这可能不是您正在寻找的完整答案,但您的代码有一些改进。尝试以下操作:

public function useResource() {
    $mysqli = secureMysqli();
    // add `` backticks around table and column names to prevent mysql reserved words error
    if ($stmt = $mysqli->prepare("UPDATE `resource` SET `is_in_use` = 1 WHERE `is_in_use` = 0 AND `id` = ?")) {
        $stmt->bind_param('i', $this->id);
        $stmt->execute(); // No need to check if is executed.

        if($mysqli->affected_rows == 1) {
             return true;
        } else {
             return false;
        }
   }
   return false;
}

如果您确实想检查查询是否正确执行,请添加:

if( !$stmt){
  echo $mysqli->error;
}

您可以将其添加到每个 $stmt 调用下,因此也可以添加到准备、绑定(bind)和执行语句下

关于php - MySQL UPDATE 语句未按预期锁定行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32016456/

相关文章:

php - MySQL 更新时间

php - 获取所有与另一个表不匹配的行

PHP - 将 2d 数组转换为按特定值分组的 3d 数组的最快方法

MySQL 按字母顺序排序但忽略 "The"

mysql - 如何一次删除 taggregate_temp_ 表?

mysql - 让 InnoDB 只锁定当前正在更新的行?

PHP OOP 架构问题(OOP against Roles)

php - WordPress:多站点帖子查询的过滤器类别

c# - 在多个线程中锁定一个变量

sql - SELECT 语句中 NOLOCK 提示的效果