【问题标题】:SELECT...FOR UPDATE with prepared statement is not workingSELECT...FOR UPDATE 与准备好的语句不起作用
【发布时间】:2013-08-29 08:37:38
【问题描述】:

我正在尝试创建一个类似 fb 的按钮功能(不是 facebook api)。 我的网站上有两个按钮:喜欢和不喜欢。 数据库将保存总共有多少喜欢和不喜欢。

这是数据库表:

id |post_id |like_count
40 |     20 |         0

用户点击赞按钮时的代码:

$id = 40;
$conn->autocommit(FALSE);
$conn->query("BEGIN;");

//lock the row to prevent race condition
$sql = "SELECT like_count FROM post_like WHERE id = ? LIMIT 1 FOR UPDATE";
$stmt = $conn->prepare($sql);
$stmt->bind_param('i', $id);
$stmt->execute();
$stmt->close();

//update the table
$sql = "UPDATE post_like SET like_count = like_count + 1 WHERE id = ? LIMIT 1";
$stmt = $conn->prepare($sql);
$stmt->bind_param('i', $id);
$stmt->execute();
$stmt->close();

$conn->commit();
$conn->autocommit(TRUE);
$conn->close();
//when success, display unlike button to user throught AJAX

以及用户点击不同按钮时的代码:

$id = 40;
$conn->autocommit(FALSE);
$conn->query("BEGIN;");

//lock the row to prevent race condition
$sql = "SELECT like_count FROM post_like WHERE id = ? LIMIT 1 FOR UPDATE";
$stmt = $conn->prepare($sql);
$stmt->bind_param('i', $id);
$stmt->execute();
$stmt->close();

//update the table
$sql = "UPDATE post_like SET like_count = like_count - 1 WHERE id = ? LIMIT 1";
$stmt = $conn->prepare($sql);
$stmt->bind_param('i', $id);
$stmt->execute();
$stmt->close();

$conn->commit();
$conn->autocommit(TRUE);
$conn->close();
//when success, display like button to user throught AJAX

这就是问题...
like_count 的数量从 0 开始。
理论上,如果只有一个人点击按钮,like_count不会超过1也不小于0。
(点赞按钮->->锁定行->like_count+1->释放行->显示不一样按钮)
(点击不像按钮->锁定行->like_count-1->释放行->显示像按钮)
当我缓慢单击按钮时,我可以正确地完成这项工作,但是,当我继续快速单击按钮时,like_count 的数量可能会超过 2,有时可能是负数。
我不知道我做错了什么。请帮忙!

【问题讨论】:

  • 最后一次更新,为什么执行在bind_param之前?
  • 让我问你一个问题。这里的比赛条件有什么问题?

标签: php transactions mysqli prepared-statement table-locking


【解决方案1】:

在您的更新查询中 放

$stmt->execute();

下面

$stmt->bind_param('i', $id);

【讨论】:

  • 是的,执行();在我正在使用的代码中的 bind_param 下面,只是在这里发布代码时出错,这是我的第一篇文章,感谢您指出这一点
【解决方案2】:

处理所有按钮的代码。

$amount = (isset($_POST['like'])) ? 1 : -1;
$sql    = "UPDATE post_like SET like_count = like_count + ? WHERE post_id = ?";
$stmt   = $conn->prepare($sql);
$stmt->execute(array($amount,$_POST['id']));

请注意,您不需要此表中的 id 列。 post_id 没问题

【讨论】:

  • 此代码并非旨在解决您的任何问题,请注意。这是在 PHP 端处理按钮的正确代码。而对于您的特定问题,您必须首先找出您遇到的问题是什么
【解决方案3】:

变化:

$conn->autocommit(FALSE);

收件人:

$conn->autocommit(TRUE);

更新和插入查询不适用于$conn->autocommit(FALSE);

【讨论】:

    猜你喜欢
    • 2018-01-24
    • 2021-01-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-09
    • 2015-10-11
    相关资源
    最近更新 更多