thinkphp 大批量插入数据提示 Duplicate entry for key PRIMARY
SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry 'yizuotu.net' for key 'name'插入线程频率较高,没有处理好事务,造成插入sql执行顺序混乱
thinkphp5 模型多次save操作和insert,会产生重复的主键ID
thinkphp6 thinkphp8 甚至其他php也可以提示类似的错误的解决方法
在数据表导入的时候出现Duplicate entry ‘xxx’ for key ‘PRIMARY’错误
在thinkphp5.0.7版本下使用,如果用模型多次执行save操作,会提示产生的主键name重复。
原因:
建了主键的字段,重复数据反复插入
为什么会反复插入:例如有些特定环境,为了确保信息插入,同一条信息会提交N次
本来你的基本流程是:
1)先判断是否存在,不存在才插入
$ok = Db::name('yizuotu')->field("name")->where('name', $name)->find();
if ($ok){
echo "已经存在";
}else{
echo "不存在才插入:";
$p = Db::name('yizuotu')->insertGetId(['name'=>$name]);
if ($p){
echo "成功插入";
}
}
2)而实际操作中,以上语句经常无效,根本没有过find(),就提示 重复数据,然后抛出错误
猜测:同一时间大量数据提交,mysql反应不过来
3)解决方法:
有条件写队列 redis,再慢慢出队列入库
捡便宜方法:INSERT IGNORE 忽略重复 或者 replace
Db::name('yizuotu')->replace()->insert(['name'=>$name]);
注意加:INSERT IGNORE 的话,找到文件:
thinkphp5增加过滤重复:
需更改框架文件:thinkphp\library\think\db\Query.php
$sql = str_replace('INSERT INTO', 'INSERT IGNORE INTO', $sql);
thinkphp6和thinkphp8过滤重复:
需更改框架文件:\vendor\topthink\think-orm\src\db\builder\Mysql.php
!empty($options['replace']) ? 'REPLACE' : 'INSERT',
直接改成 !empty($options['replace']) ? 'REPLACE' : 'INSERT IGNORE',
当然具体根据自己的需要调整
调整以后,相同主键的数据只插入1次,重复插入直接忽略
replace 就是用个最新的替换老数据