问题:
1.高并发时,数据库插入操作抛出DuplicateKeyException异常;
2.批量插入数据的时,数据库插入操作抛出DuplicateKeyException异常;
异常信息如下:
org.springframework.dao.DuplicateKeyException: ....(具体信息省略......)
解决方案:
方案一:捕获异常,适用于需要对异常处理的程序,如交易订单号重复,给客户友好提示;
try{
// 入库操作
inset into ...
}catch (DuplicateKeyException e){
// 返回响应信息或或略
}
方案二:数据库层面上进行忽略,这样遇到重复值就会跳过,后面的数据任然可以插入,适用于对单条数据的操作要求不严 格,如批量处理数据;
1.insert ignore into ...
当插入数据时,如出现错误时,如重复数据,将不返回错误,只以警告形式返回。
所以使用ignore请确保语句本身没有问题,否则也会被忽略掉。
例如:
INSERT IGNORE INTO table (XXX) VALUES ('xxx')
这种方法很简便,但是有一种可能,就是加入不是因为重复数据报错,而是因为其他原因报错的,也同样被忽略了。
2.on duplicate key update
当primary或者unique重复时,则执行update语句,如update后为无用语句,如id=id,则同1功能相同,但错误不会被忽略掉。
例如:
INSERT INTO table (XXX) VALUES ('xxx') ON duplicate KEY UPDATE id = id
这种方法的前提条件,就是,需要插入的约束,需要是主键(primary key)或者唯一约束(unique key)。
3.insert … select … where not exist
根据select的条件判断是否插入,可以不光通过primary key 和unique来判断,也可通过其它条件。
例如:
INSERT INTO table (XXX) SELECT 'xxx' FROM dual WHERE NOT EXISTS (SELECT id FROM table WHERE id = 1)
这种方法其实就是使用了mysql的一个临时表的方式,但是里面使用到了子查询,效率也会有一点点影响,不是很推荐级。
4.replace into
如果存在primary key or unique相同的记录,则先删除掉。再插入新记录。
例如:
REPLACE INTO table SELECT 1, 'xxx' FROM table
这种方法就是不管原来有没有相同的记录,都会先删除掉然后再插入。
方案三:在对数据操作之前,先去数据库查重,然后对数据操作加锁或休眠线程等待,例如:redis 或线程sleep;不推荐, 浪费系统性能,降低了系统的效率;
原因:
mysql在批量插入数据的时候,如果有一个字段具有unique约束或是primary key ,而插入数据重复的话,就会抛出DuplicateKeyException,导致后续批量数据无法插入;
相关知识点:
1.异常处理;
2.数据库操作语句;
3.锁机制;
代码示例:
如上。