我需要在我的一个项目中使用batchid,一行或多行可以有单个batchid。所以当我从一个用户插入1000行时,我会给这1000行一个batchid。此批处理ID是下一个自动增量批处理ID。
目前,我为唯一的id维护一个单独的数据库表,并在其中存储最后一个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();`

但真正的问题是,当一秒钟内同时有数百个请求时,它会为两个不同的批提供相同的批ID。这对我来说是个严重的问题。我需要解决这个问题。
请建议我该怎么做?我可以只限制这个类的一个实例,这样就不会有同时的请求一次调用这个函数,也不会给两个不同的批分配一个batchid。

最佳答案

查看原子操作或事务。它将锁定数据库,并且在任何给定实例上只允许一个写查询。
这可能会影响您的性能,因为现在其他用户必须等待解锁的数据库!
不过,我不确定adodb为atomicity提供了什么样的支持!
基本概念是:

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

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

09-25 21:53