简体   繁体   中英

What is the best way to manually increment counter in PHP/MySQL?

I am need to use batchId in my one of project, one or more rows can have single batchId. So when I will go to insert a bunch of 1000 rows from a single user, I will give this 1000 rows a single batchId. this batchId is next autoincrement batchId.

Currently I maintain a separate database table for unique_ids, and storing last batchId there. Whenever I need to insert a batch of rows in table, I update the batchId in unique_ids table by 1 and use it for batch insertion.

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

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

I call up a function which fires above two queries and return me the nextId for batch (batchId).

Here is my PHP class and function call for same. I am using ADODB, You can ignore that ADODB related code.

        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'];
                }
        }

Now whenever I require a next batchId, I just call below line of code.

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

But the real problem is When there are hundreds of simultaneous requests in a second, It gives same batchId to two different batches. It is a serious issue for me. I need to solve that.

Please suggest me what should I do? can I restrict only a single instance of this class so no simultaneous requests can call this function at a time and never give a single batchId to two different batches.

Have a look into atomic operations or transactions. It will lock the database and only allow one write query at any given instance in time.

This might affect your performance, since now other users have to wait for a unlocked database!

I am not sure what sort of support ADODB provides for atomicity though!

Basic concept is:

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

If a lock is already acquired, the script will be blocked (busy waiting) until it is released again. But this way you are guaranteed no data hazards occur.

Begin tran Update Select Commit

That way the update locks prevents two concurrent runs from pulling the same value.

If you select first,the shared lock will not isolate the two

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM