- 应用场景
程序需生成编码(唯一)作为外包装的打印喷码,随机且唯一;目前操作一键生成超过5000条时,脚本执行时间过长。
排查后发现代码如下(伪代码演示):
$num = 5000; // 需要生成数据数量
// 循环
for ($i = 0; $i < $num; $i++) {
do {
$sn = getSn(); // 生成随机码
$rowCount = pdoCount('table_sn', array('sn' => $sn)); // 数据库查重
} while ($rowCount);
$insert_data... // 插入数据准备
pdoInsert('table_sn', $insert_data); // 插入数据
}
- 填坑中
处理屎山总是让人兴奋且有成就感。。。
第一反应的思路,已存在的sn可以先遍历出来,在脚本中筛除而不是通过mysql;考虑到会有同时操作业务的情况,多个线程并发执行会造成脏写、幻读。
最终的解决方案:table_sn表新增sn字段的唯一索引进行约束,利用mysql的INSERT IGNORE方式插入
最终实现代码如下(伪代码演示):
$num = 5000; // 待插入数量
while ($num) { // 循环
$sn = getSn(); // 生成随机码
$insert_data... // 插入数据准备
pdoQuery('INSERT IGNORE table_sn ...'); // 忽略插入
$hasInsert = pdoInsertid(); // 是否插入成功
if ($hasInsert) {
$num--;
}
}
- 小结
业务问题必然无最优解,这次的方案可能还会遇到死循环(id自增失败/字段格式填写错误/必填字段报错等原因无法插入),重复写入(生产部署后未添加唯一约束)等等,代码只有在迭代的时候最完美。
本文由 ben 创作,采用 知识共享署名4.0 国际许可协议进行许可
本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名
最后编辑时间为: Aug 23, 2021 at 05:41 pm