mysql批量插入时,uuid产生的主键是同一个值

起因:
遇到一个定时器产生的数据记录与理论值存在差异,将sql拷贝到Navicat客户端执行后,发现不止数据值存在偏差,插入的数据量只有一条。
sql如下:
insert into table_a(id,col1,col2,col3) select replace(uuid(),'-','') id,p.col1 ,p.col2,p.col3
from (select q.col1,q.col2,q.col3 from pl_info q ) p on duplicate key update col3 = p.col3

用于将查询到的结果集插入到表中,如果唯一索引(col1,col2)冲突则不插入而修改字段值。
分析:
截取查询部分进行执行,执行结果有145条数据,全部执行结果只参数一条新数据。
开始以为是on duplicate key update受到如mysql版本或者什么影响导致,于是百度,无果!对sql进一步拆分分析后,在不使用on duplicate key update时,会导致主键冲突,查看查询sql结果集,replace(uuid(),'-','')产生的uuid都是一样的。
问题原因:
sql语句里的replace(uuid(),'-','')产生的uuid是一样的。
查找为什么:
网上了解到通过Navicat客户端执行sql语句会存在这个问题。
进一步对比发现,调用测试环境接口执行的该sql语句,同样会存在该问题。
所以应该是受到某个具体的因素影响导致,继续查询资料,得到造成该问题的是数据库字符集utf8mb4的原因。
对比:
1,对比测试环境,正式环境的数据库字符集:show VARIABLES like '%char%'

正式环境测试环境

区别在于测试环境的character_set_server的字符集为utf8mb4。
将本地数据库的character_set_server改成utf8mb4后重启mysql服务,调用本地服务接口执行sql语句,得到与测试环境相同的问题。
2,因为使用Navicat查询,不管正式还是测试环境,都会存在该问题;
单独修改Navicat的character_set_client的值为utf8,再次执行sql,发现问题仍然存在;
单独修改Navicat的character_set_connection的值为utf8,再次执行sql,发现不存在该问题。
结论:
批量产生无-的uuid方法replace(uuid(),'-',''),受到character_set_server和character_set_connection两个字符集参数的影响,当字符集为utf8mb4时,产生的uuid会相同,导致插入时主键冲突。
uuid()则不受影响。
后续:
问:如何通过修改sql语句避免该问题?方案:
1、先使用uuid()函数产生id,外层再包裹一层查询,使用replace(id,'-','')进行去-操作;(没有效果,产生的id仍然相同)
2、使用保证唯一的有规律字符串替换uuid,如上sql可以将stc_id,in_account_date组装成特定序列,作为ID;
3、使用md5()对产生的uuid()做进一步转换,即md5(uuid());(有效,产生的id不会相同)

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
MySQL官方不建议使用UUID作为主键的原因有以下几点: 1. 存储空间占用:UUID是一个128位的字符串,相比于自增的整数类型主键,它需要更多的存储空间。这在大规模的数据表中会占用较多的磁盘空间,影响数据库性能。 2. 索引效率:UUID是随机生成的字符串,不具有连续性。在使用UUID作为主键,每次插入新记录都需要在索引树中找到合适的位置,这会导致索引的频繁更新和碎片化,降低了查询效率。 3. 数据库性能:由于UUID是随机生成的,插入新记录需要生成一个唯一的UUID。这个过程需要消耗较多的计算资源,对于高并发的数据库操作来说,会增加数据库的负载,降低性能。 4. 数据库复制和同步:如果使用UUID作为主键,那么在数据库复制和同步的过程中,会增加数据传输的开销。因为UUID是随机生成的,每个节点生成的UUID都不同,导致数据同步需要传输更多的数据。 综上所述,MySQL官方推荐使用自增的整数类型主键(如auto_increment)而不是UUID作为主键,这样可以提高数据库的性能和效率。但是在某些特定的场景下,如分布式系统或需要跨数据库同步的情况下,使用UUID作为主键可能更合适。 #### 引用[.reference_title] - *1* [MySql为什么不推荐使用UUID主键](https://blog.csdn.net/chenwiehuang/article/details/123420278)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [MySQL中如何将主键默认设为UUID()](https://blog.csdn.net/qq_43739097/article/details/104383456)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值