生成顺序唯一码,经常出现重复录入错误

Generating sequential unique code, often times occurs duplicate entry error

我目前正在使用 PHP & Laravel。

我想做的是生成一个唯一的顺序字符串作为代码。
在此示例中,代码用于采购订单。

我想要的是这样的:

PO/000001
PO/000002
PO/000003
PO/000004
PO/000005
PO/000006

数据库table架构:

create table `purchase_orders` (
`id` int unsigned not null auto_increment primary key,
`code` varchar(191) not null, 
...
...
)

alter table `purchase_orders` add unique `purchase_orders_code_unique`(`code`)

这看起来很简单,我只需要获取auto_increment ID,所以code对应id,大致是这样的:

id | code
 1 | PO/000001
 2 | PO/000002
 3 | PO/000003
 4 | PO/000004
 5 | PO/000005
 6 | PO/000006

我使用的代码:(使用Laravel的ORM语法)

$count = PurchaseOrders::max('id'); // Equivalent to select MAX (`id`) from purchase_orders
$code = 'PO/' . sprintf('%08d', $count + 1);

理论上它很好用,但实际上,经常会发生 'collision',其中 id 不等于它生成的 code,有时 codeid bigger/ahead。比如经常会这样:

 id | code
... | ...
199 | PO/000199
200 | PO/000200
201 | PO/000202

下一笔交易将具有 202id,生成的 code 应该是 PO/000202。它将触发 Integrity constraint violation 错误,因为 PO/000202 已在 id: 201.

上使用

我大量使用数据库事务和提交,有时创建采购订单需要一些时间,而且有多个用户正在创建采购订单。我不知道它到底是怎么发生的,但是冲突经常发生,大约有 100 个交易。


这是一个实时项目中发生的事件:

如您所见,code 大于 id。下一个要插入的代码是...000205,我的客户端报错:

SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry   
'PRCV/JKT/G/2019/00000205' for key 'dlvr_payments_code_unique'

你也可以看出idcode根本不相等


我之前也试过其他的代码生成方式,我用MAX('id')代替MAX('id'),但是好像比MAX('id').

那么,问题来了,我做错了什么?我怎样才能让它每次都确保唯一的代码,这样以后就不会再发生这种情况了?

我一直在考虑使用 Redis 或一些键值数据库来存储计数,是否有必要?

不要这样做!

不要依赖PK来实现序号。它让你在不同的尽头街道。

我建议将您最后插入的 采购订单 ID 存储在单独的 table 中,并相应地不断更新它。

在维护 table 的同时,将其存储在缓存(即 Redis)中可以提高应用程序的性能。

希望对您有所帮助!