MySQL数据库事务可重复读无法解决第二类丢失更新
问题背景:
账单结算完成时需要更新对应账户余额。如果多笔账单同时结算完成,此时会同时更新账户余额。更新的步骤为,先查询账户当前余额,然后累加上本次账单金额,然后更新。例如,账单1和账单2同时查到当前账户余额为10元,其中账单1金伟为5元,于是先将余额更新为10+5=15元并提交事务,账单2金额为8元,并将余额更新为10+8=18元也提交事务。最后账户余额为18元。
检查事务隔离级别为可重复读。数据库为mysql。
排查原因:
mysql数据库,通过设置事务隔离级别为可重复读(REPEATABLE_READ)无法避免发生“第二类丢失更新”问题。(问题参见:https://www.it1352.com/1667833.html)
第二类丢失更新:
解决方案:
A. 悲观锁方案:
1. 开启事务的方法执行之前先加锁(分布式环境需要加分布式锁)。特别注意:在事务方法内部的某个步骤加锁,是无效的,因为这一步骤执行完毕释放锁后,当前事务仍未提交,若在此期间另一个事务B已经开始执行,那么事务B仍然会拿到之前提交的数据。
B. 乐观锁方案:
1. 执行更新SQL语句时,条件中增加对数据版本的判断,必须是对查询到的那个版本的数据进行更新,且update语句执行完毕后检查更新行数,如果更新时版本号已发生改变,此时update语句返回的行数肯定预期的行数,此时可认定为查询后更新前这段时间数据已发生改变,抛出异常,然后重试
事务相关参考:
https://blog.csdn.net/paopaopotter/article/details/79259686
https://www.cnblogs.com/snsdzjlz320/p/5761387.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)