首页 > 数据库 >Mysql 数据库并发事物导致ABA问题排查解决

Mysql 数据库并发事物导致ABA问题排查解决

时间:2024-11-25 18:45:58浏览次数:5  
标签:ABA where 事物 更新 并发 Mysql table 数据 id

问题描述

一个更新计费参数接口,按钮连点导致数据未更新问题。

背景

接口内容逻辑,在一个事物内,先保存更新计费参数,再根据计费参数,重新计算费用,并刷新计费单,结算单,支付单等单据金额信息。

按理来讲,这个接口是具备幂等性的,因为即便多次更新,也只是重新计算一遍,数据结果不会改变。
但这个问题现象是两次并发操作导致数据不发生变化,相当于一次操作更新了,但另一次操作给还原了。

过程分析

事物1 事物2
select * from table where id = ?; // 对数据做校验 select * from table where id = ?; // 对数据做校验
// 事物2 更新语句先执行,锁住当前行,等待事物2结束 update table set fee = ?,update_time = ? where id = ?; //保存费用配置并通过更新当前事物数据为最新行数据

//调用统一刷新费用方法
select * from table where id = ?; // 查询最新数据
update table set fee = ?, amount = ?, update_time = ? where id = ?; //更新业务数据(根据fee新值,计算出新值 amount 并更新)
//事物结束,释放行锁
update table set fee = ?, amount = ?,update_time = ? where id = ?; //保存费用配置并通过更新当前事物数据为最新行数据,(因另一事物已更新,SQL执行成功,但因数据一样,未实际更新数据)
//调用统一刷新费用方法
select * from table where id = ?; // 查询最新数据(MVCC 旧数据)
update table set fee = ?, amount = ?,update_time = ? where id = ?; //更新业务数据(导致根据fee旧值,计算出旧值 amount 并更新覆盖新值 )

因操作连点,两个事物在1秒内完成,因此更新时间的差额在毫秒级,数据库更新时间字段使用 timestamp 类型精确到秒,导致事物2执行完后,事物1第一次更新时,更新数据和数据库行数据是一致的,所以更新sql执行了,但没有实际更新数据,导致当前事物还是快照读,因此当前事物看不到最新行数据,还是使用事物1原本的旧数据。
所以在统一刷新费用方法中,重新根据id查询时,还是旧数据,导致费用数据又被更新为旧数据。

解决办法

  • 数据库更新时间字段使用 timestamp(3),精确到毫秒级,保证更新成功,事物当前读,可以获取到最新行数据。
  • 事物开头主动锁行,使用当前读,避免使用快照读:select * from table where id = ? for update,保证获取最新数据并阻塞其他事物。
  • 操作增加分布式锁,锁粒度为当前订单,避免同时操作同一订单的修改操作。
  • 前端按钮增加连点控制。

标签:ABA,where,事物,更新,并发,Mysql,table,数据,id
From: https://www.cnblogs.com/crazy-dev/p/18568370

相关文章

  • MySQL数据库与Informix:能否创建同名表?
    MySQL数据库与Informix:能否创建同名表?一、MySQL数据库中的同名表创建1.使用CREATETABLE...SELECT语句2.使用CREATETABLELIKE语句3.复制表结构并选择性复制数据4.使用同义词(Synonym)二、Informix数据库中的同名表创建1.使用不同所有者2.使用不同......
  • MySQL与Informix数据库中的同义表创建:深入解析与比较
    MySQL与Informix数据库中的同义表创建:深入解析与比较一、同义表的基本概念与用途1.定义与概念2.主要用途二、MySQL数据库中的同义表创建1.使用视图创建同义表2.使用别名创建同义表3.MySQL中的同义表限制与替代方案三、Informix数据库中的同义表创建......
  • k8s问题记录-etcdserver: mvcc: database space exceeded异常处理
    报错截图如下查看etcd,发现超过默认值2G了解决参考链接https://cloud.tencent.com/developer/article/2360418执行过程PS:高可用集群需要在所有master执行#1、获取当前的版本$rev=$(ETCDCTL_API=3etcdctl--endpoints=https://127.0.0.1:2379--cacert=/etc/kubernete......
  • mysql数据库聚合与拆分
    1.背景在用户使用的时候会有统计数据的情况,在多表联查的时候分类时会有,同一个类型出现多次,然后任务需区是出现一次类型名2.聚合查询GROUP_CONCAT(聚合字段)  group_by(聚合字段)SELECTreport.serialNumberas'病人编号',GROUP_CONCAT(label.lableName)AS"标签名"......
  • 40分钟学 Go 语言高并发:【实战】并发安全的配置管理器(功能扩展)
    【实战】并发安全的配置管理器(功能扩展)一、扩展思考分布式配置中心实现配置的集中管理支持多节点配置同步实现配置的版本一致性配置加密敏感配置的加密存储配置的安全传输访问权限控制配置格式支持支持YAML、TOML等多种格式配置格式自动识别和转换支持环境变量替换......
  • 40分钟学 Go 语言高并发:【实战】并发安全的配置管理器
    【实战】并发安全的配置管理器一、课程概述学习要点重要程度掌握目标配置热更新★★★★★理解配置热更新原理,实现动态加载配置并发读写控制★★★★★掌握并发安全的读写控制机制观察者模式★★★★☆理解并实现配置变更通知机制版本管理★★★★☆实现配置版本控制和回......
  • MySQL误删表数据,如何快速恢复丢失的数据?
    第一步:登录数据库cd/www/server/mysql/binmysql-uroot-p第二步:查看binlog日志是否打开showvariableslike'log_%'; 查看下binlog日志列表binlog日志文件目录在/www/server/data目录下showmasterlogs; 下载生成sql文件/www/server/mysql/bin/mysq......
  • MySql:库和表的操作
    ✨✨作者主页:嶔某✨✨✨✨所属专栏:MySql✨✨ 库的操作创建数据库 CREATEDATABASE[IFNOTEXISTS]db_name[create_specification[,create_specification]...]create_specification:[DEFAULT]CHARACTERSETcharset_name[DEFAULT]COLLATEcollation_name......
  • 【史上最强的安装离线Mysql8.1教程】
    安装Mysql8.1教程Mysql是一种开源的关系型数据库管理系统,它被广泛应用于Web应用程序开发。本教程将帮助您了解如何安装MySQL8.1。步骤1:下载Mysql8.1mysql社区官方:https://downloads.mysql.com/archives/community/首先,您需要前往MySQL官方网站(https://www.mysql.co......
  • 【Z2400010】基于java+ssm+mysql+layui的学籍管理系统的设计与实现(附源码 配置 文档)
    基于ssm+layui的学籍管理系统1.摘要2.系统功能3.系统数据库4.界面展示5.源码获取1.摘要本系统是一个基于SSM(Spring+SpringMVC+MyBatis)框架和Layui前端框架的学籍管理系统,旨在帮助新手快速上手JavaWeb项目的整体运行流程,并熟悉此类项目的搭建过程。系统界面简洁明......