gpt4 book ai didi

php - 在 MySQL 中制作一个可靠的计数器

转载 作者:行者123 更新时间:2023-11-28 23:21:00 26 4
gpt4 key购买 nike

我想在使用 MySQL 数据库的 PHP 编写的应用程序中创建一个计数器。用户提供一个字符串作为输入。此字符串表示数据库记录的键。它存储一个整数计数器值。用户取回增加后的值。

我现在是这样做的:

// connect to database
try {
$db = new PDO('mysql:host='.$dbhost.';dbname='.$dbname, $dbuser, $dbpasswd);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
} catch(Exception $ex) {
echo "DB Error: ".$ex->getMessage();
exit;
}

// update and get new value
try {
$db->beginTransaction();
$nc = updateNC($db, $grundsig, $library);
$db->commit();
} catch(Exception $ex) {
$db->rollBack();
$err = 'DB Error: '.$ex->getMessage();
}

// [...]

function updateNC($db, $grundsig, $library) {

// increment counter ("nc")
$query = $db->prepare('
update numeruscurrens n
join libraries l using(libid)
set n.nc = n.nc+1
where n.grundsig = :grundsig and l.libname = :libname
');
$query->execute([
':grundsig' => $grundsig,
':libname' => $library
]);

// get new counter value
$query = $db->prepare('
select *
from numeruscurrens n
join libraries l using(libid)
where n.grundsig = :grundsig and l.libname = :libname
');
$query->execute([
':grundsig' => $grundsig,
':libname' => $library
]);
$result = $query->fetchAll();
return $result[0]['nc'];
}

重要的部分发生在updateNC 函数中。我执行更新以增加计数器,并且我想要新的计数器值。

现在的问题是在这两个命令之间另一个用户可以进行更新。两个用户可能会得到错误的计数器值。

我如何才能可靠地增加计数器并为该用户获取新值?

我还考虑过使用像 Redis 这样的键值数据库,它有 INCR命令。但我认为这有点夸张。

最佳答案

如果您想要确保它们将获得立即增加的值,那么您应该在提交事务之前使用一种方法来锁定您要更新的行。这可以使用 FOR UPDATE 提示和先前的 SELECT 查询锁定您要更新的行来完成。

我将只添加 SQL 代码以关注实际问题。

SET @counter = 0;

BEGIN;

SELECT n.nc INTO @counter
FROM numeruscurrens n
JOIN libraries l using(libid)
WHERE n.grundsig = @grundsig and l.libname = @libname
FOR UPDATE;

update numeruscurrens n
join libraries l using(libid)
set n.nc = n.nc+1
where n.grundsig = @grundsig and l.libname = @libname

/* You are always incrementing, aren't you? */
SET @counter = @counter + 1;

SELECT @counter;

COMMIT;

另请注意,这不是免费的。实际上必须要求将此增量值正确返回给用户,因为此锁定会因行锁定而对性能产生负面影响,并可能造成死锁。最后但同样重要的是,确保表使用的是 InnoDB 引擎。 MyIsam 不支持行级锁。

关于php - 在 MySQL 中制作一个可靠的计数器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41585325/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com