php - 在 PHP/MySQL 中手动增加计数器的最佳方法是什么?

标签 php mysql

我需要在我的一个项目中使用 batchId,一行或多行可以有一个 batchId。因此,当我要从单个用户插入一堆 1000 行时,我会给这 1000 行一个单一的 batchId。此 batchId 是下一个自动增量 batchId。

目前我为 unique_ids 维护一个单独的数据库表,并将最后一个 batchId 存储在那里。 每当我需要在表中插入一批行时,我将 unique_ids 表中的 batchId 更新为 1,并将其用于批量插入。

update unique_ids set nextId = nextId + 1 where `key` = 'batchId';

select nextId from unique_ids where `key` = 'batchId';

我调用了一个函数,该函数触发了两个查询并返回批处理的 nextId (batchId)。

这是我的 PHP 类和函数调用。我用的是ADODB,你可以忽略ADODB相关的代码。

        class UniqueId
        {
                static public $db;

                public function __construct()
                {

                }

                static public function getNextId()
                {
                        self::$db = getDBInstance();        
                        $updUniqueIds = "Update unique_ids set nextId = nextId + 1 where `key` = 'batchId'";
                        self::$db->EXECUTE($updUniqueIds);

                        $selUniqueId = "Select nextId from unique_ids where `key` = 'batchId'";
                        $resUniqueId = self::$db->EXECUTE($selUniqueId);

                        return $resUniqueId->fields['nextId'];
                }
        }

现在每当我需要下一个 batchId 时,我只需调用下面的代码行。

`$batchId = UniqueId::getNextId();`

但真正的问题是当一秒钟内有数百个并发请求时,它会为两个不同的批处理提供相同的 batchId。这对我来说是个严重的问题。我需要解决这个问题。

请建议我该怎么做?我能否仅限制此类的单个实例,以便没有同时请求可以一次调用此函数并且永远不会将单个 batchId 提供给两个不同的批处理。

最佳答案

查看原子操作或事务。它将锁定数据库,并且只允许在任何给定实例上及时进行一次写入查询。

这可能会影响您的性能,因为现在其他用户必须等待解锁的数据库!

我不确定 ADODB 为 atomicity 提供了什么样的支持虽然!

基本概念是:

Acquire Lock
Read from DB
Write to DB with new ID
Release Lock

如果已经获得锁,脚本将被阻塞(忙等待),直到它再次被释放。但通过这种方式可以保证不会发生数据危害。

关于php - 在 PHP/MySQL 中手动增加计数器的最佳方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11277311/

相关文章:

PHP MYSQL 在这些日期之间使用此值选择 *

php - 如何将网站帖子转换为pdf?

php - 上传时调整图像大小

MySQL 函数 IFNULL 无法与通配符一起正常工作

MySQL:如果 JOIN 期间缺少表行,则为 "Ignore"

php - 从 block 中的大表中提取报告

php - 如何使用 PHP MySql 搜索搜索查询中的每个单词

php - 如何显示所选分类的分类父级

mysql - 努力使用promise-mysql和bluebird从mysql取回数据

mysql - 尝试连接三个表,其中主表与子表没有直接关系