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

时间:2012-06-30 20:11:31

标签: php mysql

我需要在我的项目中使用batchId,一行或多行可以有单个batchId。因此,当我要从单个用户插入一堆1000行时,我将为这1000行提供一个batchId。这个batchId是下一个autoincrement 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分配给两个不同的批次。

2 个答案:

答案 0 :(得分:3)

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

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

我不确定ADODB为atomicity提供了哪种支持!

基本概念是:

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

如果已获取锁定,则将阻止脚本(忙等待),直到再次释放。但是这样可以保证不会发生数据危害。

答案 1 :(得分:-2)

开始tran 更新 选择 提交

这样,更新锁会阻止两个并发运行提取相同的值。

如果先选择,则共享锁不会隔离两个