MySQL行级锁解决消费队列中出现的唯一主键错误
来源:SegmentFault
时间:2023-02-16 15:38:34 306浏览 收藏
编程并不是一个机械性的工作,而是需要有思考,有创新的工作,语法是固定的,但解决问题的思路则是依靠人的思维,这就需要我们坚持学习和更新自己的知识。今天golang学习网就整理分享《MySQL行级锁解决消费队列中出现的唯一主键错误》,文章讲解的知识点主要包括MySQL,如果你对数据库方面的知识点感兴趣,就不要错过golang学习网,在这可以对大家的知识积累有所帮助,助力开发能力的提升。
前言:最近项目中的定时任务消费队列一直出现一个重复的唯一主键错误,是多个事务对同一行数据进行操作引起的。解决这个问题后,我便写了这篇博客的草稿,由ctx同学强势审核修改后,便有了这一版本的博客。
场景复现
出错方法:
@Transactional
public void handleAccountRisk(String accountUuid, float risk, RiskConfEtcdVo riskConf, Long currentTimeSeconds) {
// 分布式锁
String redisKey = RISK_UPDATE_LOCK_KEY.re~~~~place("${item}", accountUuid);
String businessId = BusinessIdGeneratorUtil.businessId();
redissonLockUtil.lock(redisKey,businessId, () -> {
AccountRiskEntity accountRisk = accountRiskTplDao.getAccountRiskByUuid(accountUuid);
// 如果accountRisk不存在则新增
if (null == accountRisk) {
// 实例化一个对象后填充...
// insert
accountRiskTplDao.save(target);
// 如果存在则更新
} else {
...
accountRiskTplDao.updateById(accountRisk);
...
}
});
}报错信息:
INSERT INTO account_risk ( create_time, update_time, risk, uuid ) VALUES ( ?, ?, ?, com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry 'dc57ktzmtiwp' for key 'uuid'
问题分析
从Duplicate entry推断出重复插入。具体原因为:
多个事务在执行这个方法。
事务A:根据uuid查不到数据,实例化一个实体,insert,但还未提交事务
事务B:根据uuid查不到数据,实例化一个实体
此时 :A提交了事务,B执行insert
事务B:insert中出现报错:public AccountRiskEntity getAccountRiskByUuid(String uuid){ QueryWrapperqueryWrapper = new QueryWrapper(); queryWrapper.eq("uuid",uuid); // 悲观锁 queryWrapper.last("FOR UPDATE"); return baseMapper.selectOne(queryWrapper); } 相似场景
DDIA的第七章事务中,对这种情况有详细的举例描述。
关于InnoDB行锁
加锁方式
- 共享锁(S):select * from table_name where ... lock in share mode;
- 排他锁(X):select * from table_name where ... for update;
使用场景
如果遇到存在高并发并且对于数据的准确性很有要求的场景,是需要了解和使用for update的。 比如涉及到金钱、库存等。一般这些操作都是很长一串并且是开启事务的。如果库存刚开始读的时候是1,而立马另一个进程进行了update将库存更新为0了,而事务还没有结束,会将错的数据一直执行下去,就会有问题。所以需要for upate 进行数据加锁防止高并发时候数据出错。 记住一个原则:一锁二判三更新InnoDb行锁的实现方式:
InnoDB行锁是通过给索引项加锁来实现的,如果没有索引,InnoDB将通过隐藏的聚簇索引来对记录枷锁。没有索引的话会退化成锁表!
幻读:指当前某个事务在读取某个范围内的记录时,另外一个事务又在该范围内插入了新的记录。当之前的事务再次读取该范围的记录时,会产生幻行。---《高性能Mysql》
个人理解:当我们依据(某个事务在读取某个范围内的记录)的结果作为判断条件决定后续的操作,在另一个事务(又在该范围内插入了新的记录)后,之前判断条件的结果就可能会被改变了。违背了这个判断条件,那么后续的操作就需要保持疑问了?
好了,本文到此结束,带大家了解了《MySQL行级锁解决消费队列中出现的唯一主键错误》,希望本文对你有所帮助!关注golang学习网公众号,给大家分享更多数据库知识!
声明:本文转载于:SegmentFault 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
-
499 收藏
-
244 收藏
-
235 收藏
-
157 收藏
-
101 收藏
最新阅读
更多>
-
数据库 · MySQL | 2分钟前 | binlog · 主从复制 · 故障排查 · MySQL教程 · DBA实战 · mysql DBA binlog 主从复制 MySQL 8.4 复制延迟 relay log119 收藏
-
数据库 · MySQL | 23分钟前 | MySQL教程 · 慢查询治理 · 索引优化 · 分区表 · DBA实战 · mysql 分区表 慢查询 索引优化 MySQL 8.4 partition pruning133 收藏
-
数据库 · MySQL | 45分钟前 | 高并发 · 故障排查 · MySQL教程 · 事务隔离 · InnoDB锁 · mysql innodb 高并发 锁等待 MySQL 8.4 NOWAIT SKIP LOCKED439 收藏
-
数据库 · MySQL | 3小时前 | MySQL教程 · 慢查询治理 · 索引优化 · JSON查询 · InnoDB实战 · mysql JSON 慢查询 索引优化 MySQL 8.4 多值索引291 收藏
-
数据库 · MySQL | 22小时前 | InnoDB · 故障排查 · 生产实践 · MySQL教程 · 事务隔离 · mysql innodb Purge Lag History List 长事务 Undo326 收藏
-
数据库 · MySQL | 1天前 | 性能优化 · 执行计划 · 生产实践 · MySQL教程 · 索引优化 · mysql explain 索引优化 Index Condition Pushdown ICP179 收藏
-
189 收藏
-
数据库 · MySQL | 1天前 | 性能优化 · 执行计划 · 生产实践 · MySQL教程 · 数据库运维 · mysql 直方图 EXPLAIN ANALYZE Histogram 优化器统计信息419 收藏
-
388 收藏
-
数据库 · MySQL | 1天前 | 性能优化 · InnoDB · 生产实践 · MySQL教程 · 数据库运维 · mysql redo log innodb 性能优化 innodb_redo_log_capacity382 收藏
-
数据库 · MySQL | 1天前 | MySQL教程 · 数据库实战 · 在线DDL · ALTER TABLE · 元数据锁 · mysql innodb MySQL 8 在线 DDL ALTER TABLE MDL 元数据锁 INSTANT323 收藏
-
数据库 · MySQL | 2天前 | InnoDB · MySQL教程 · 数据库实战 · 死锁排查 · 锁等待 · mysql innodb 死锁 事务 锁等待 MySQL 8 data_locks105 收藏
课程推荐
更多>
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 485次学习

