1、错误日志
2022-09-2014:59:42.182 [Thread-119] ERROR ...ReconcSnapshot - ReconcSnapshotServiceImpl#doReconcSnapshot error! param={.....} ### Error updating database. Cause: java.sql.SQLIntegrityConstraintViolationException: Duplicate entry '157248371216629087' for key 'PRIMARY' ### The error may exist in com/...SnapshotMapper.java (best guess) ### The error may involve com...SnapshotMapper.insert-Inline ### The error occurred while setting parameters ### SQL: INSERT INTO t_reconc_snapshot ...
官方的标记为这个Bug已修复
https://github.com/baomidou/mybatis-plus/issues/3289#issue-791890470
2、原因分析
在单机单线程使用雪花算法生成的ID,是不会出现这个问题。在集群环境下,特别是在一台机器中使用Docker 部署了多个节点,同时使用多线程批量插入数据,出现唯一主键ID出现的概率非常大。
ID生成规则:
服务器时间
workId(服务器机器ID)
dataCenterId(数据标识ID部分)
3、解决方案
import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.core.incrementer.DefaultIdentifierGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MybatisPlusConfig {
/**
* description: 自定义ID主键生成器 <br>
* date: 2022/6/1 11:38 <br>
*
* @return com.baomidou.mybatisplus.core.incrementer.DefaultIdentifierGenerator
*/
@Bean
public DefaultIdentifierGenerator defaultIdentifierGenerator() {
// 以免多线程批量插入,ID主键生成有重复,主键冲突错误
// 1-31 随机数
long workerId = RandomUtil.randomLong(1, 31);
// 1-31 随机数
long dataCenterId = RandomUtil.randomLong(1, 31);
return new DefaultIdentifierGenerator(workerId, dataCenterId);
}
}
4、其它配置
MyBatis-Plus 版本 3.5.1,使用Springboot搭建的项目工程。使用MyBatis-Plus中自动生成ID主键,类型为:ASSIGN_ID (使用的雪花算法生成唯一主键ID)。
部署环境:采用一台服务器Docker多节点,多线程批量插入数据。
mybatis-plus:
global-config:
#数据库相关配置
db-config:
# 主键类型
id-type: ASSIGN_ID
或者在java中单独配置
@Data
public class ReconcSnapshot implements Serializable {
//雪花算法生成id
@TableId(value = "id",type = IdType.ASSIGN_ID)
private Long id;
...
}