php - 生成顺序唯一码,经常出现重复输入错误
问题描述
我目前正在使用 PHP 和 Laravel。
我想要做的是生成一个唯一且连续的字符串作为代码。
在此示例中,代码用于采购订单。
我想要的是这样的:
PO/000001
PO/000002
PO/000003
PO/000004
PO/000005
PO/000006
数据库表模式:
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);
理论上它工作得很好,但实际上,经常发生“碰撞”,其中id
不等于code
它产生的,有时code
大于/领先于id
. 例如,它经常这样发生:
id | code
... | ...
199 | PO/000199
200 | PO/000200
201 | PO/000202
下一笔交易将有id
of 202
,并且生成code
的应该是PO/000202
。它将触发完整性约束违规错误,因为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'
您还可以看到id
andcode
根本不相等
我之前也尝试过其他代码生成方法,而不是MAX('id')
使用COUNT(*)
,但似乎比MAX('id')
.
所以,问题是,我做错了什么?我怎样才能让它确保每次都有一个唯一的代码,这样以后就不会再发生这种情况了?
我一直在考虑使用 Redis 或者一些键值数据库来存储计数,有必要吗?
解决方案
不要这样做!
不要依赖PK来获得序号。它让你在不同的街道上。
我建议将您最后插入的采购订单ID 存储在单独的表中,并相应地更新它。
除了维护表之外,将其存储在缓存(即redis)中可以提高应用程序的性能。
希望能帮助到你!
推荐阅读
- microsoft-graph-api - 更新 privilegedRoles 需要哪些额外权限?
- flutter - Flutter,FutureBuilder 快照错误:“int”类型不是“String”类型的子类型
- python-3.x - 如何正确将此字符串转换为整数?
- javascript - Javascript中具有一维数组的锯齿状多维数组的元素过滤
- excel - Excel:如何始终链接到同一目录中的外部工作簿?
- postgresql - Postgresql 用户登录历史
- c++ - c++ 中重载函数声明的顺序是否重要?
- python - 无法让我的脚本仅从顽固网站的下一页获取链接
- r - 在箱形图上使用 geom_jitter 覆盖时标记数据点
- html - 单击文本文件并指向特定的行号