当前位置: 首页 > news >正文

Mysql:事务管理(中)

在前面的章节中,我们提到了MVCC(多版本并发控制),它巧妙地通过“版本快照”解决了“读-写”冲突,实现了非阻塞读。

但如果两个事务同时执行 UPDATE 操作修改同一行数据,即写-写(Write-Write)场景,快照就没用了。这时候,MySQL 必须亮出它的铁腕手段——锁机制

一、写-写冲突的核心问题:更新丢失

想象一下这个场景:

  • 初始状态:账户余额 100 元。

  • 事务 A:取出 100 元,准备扣款。它先读到 100,然后执行 100 - 100 = 0。

  • 事务 B:同一时刻取出 50 元,也先读到 100,执行 100 - 50 = 50。

  • 结果:如果事务 A 先提交,事务 B 后提交,B 的结果(50元)会覆盖 A 的结果(0元)。银行莫名其妙亏了 50 元。这种现象就叫“更新丢失”

二、MySQL 的解决方案:排他锁(X锁)

为了防止更新丢失,InnoDB 存储引擎采用了行级锁(Row-level Locking)

当一个事务准备修改(UPDATE/DELETE)一条记录时:

  1. 它会先尝试获取该行的排他锁(Exclusive Lock,简称 X 锁)

  2. 如果事务 A 拿到了锁:它就可以进行修改。

  3. 如果事务 B 也想修改:发现 X 锁已被 A 占用,事务 B 必须进入阻塞等待状态,直到事务 A 提交或回滚释放了锁。

结论:在“写-写”场景下,事务是串行化执行的。只有拿到锁的事务才能操作。

三、更新丢失的两个分类

在数据库理论中,更新丢失分为两类。

1.第一类更新丢失(回滚丢失):

一个事务的回滚,把另一个已经提交的事务更新的数据给覆盖了。

在 InnoDB 中,这种情况绝对不会发生

因为UPDATE会加排他锁(X 锁),事务 B 在事务 A 回滚之前根本无法修改该行数据。

2.第二类更新丢失(覆盖丢失):

一个事务基于旧数据计算新值并提交,覆盖了另一个事务已经提交的更新。

这是最常见的更新丢失。

虽然数据库有锁,但如果程序逻辑是“先读出来,在内存计算,再写回去”,锁也救不了。

四、四大隔离级别下的写-写场景

在 InnoDB 中,为了防止“脏写(Dirty Write)”,所有的隔离级别在修改数据时都会加锁

也就是说,如果事务 A 正在修改某行,事务 B 想改同一行,必须得等 A 提交或回滚。

1. 读未提交(RU) & 读提交(RC)

在这两个级别下,写-写冲突的表现最直接:

  • 锁定单行:只要事务 A 执行了 UPDATE,该行就会被加上记录锁(Record Lock)

  • 事务 B 的表现:必须阻塞等待,直到 A 释放锁。

  • 区别:在这两个级别下,MySQL 基本只锁住被修改的那些行。

2. 可重复读(RR)/串行化(Serializable)

作为 MySQL 的默认级别,RR 在写操作上比 RC “霸道”得多。

  • 间隙锁(Gap Lock)与 Next-Key Lock:RR 不仅锁住存在的记录,还会锁住记录之间的“间隙”

  • 写-写冲突升级:

    • 在 RC 下,如果事务 A 修改了 ID=10 的行,事务 B 还可以插入 ID=11 的新行。

    • 在 RR 下,如果事务 A 的写操作涉及范围(比如 WHERE id > 5),它会把整个范围都锁住。此时事务 B 想插入 ID=11 的记录也会被阻塞。

  • 目的:这是为了从根本上解决“幻读”问题,确保写操作的区间安全。

而串行化全线加锁,读也不让读。

以上两种的区别在于,RU/RC无法解决幻读,而RR/Serializable可以。

比如select * from Roles whereid > 5;

RU/RC下仍可以插入,而RR/Serializable禁止插入,杜绝了两次搜索不一样的情况。

五、写-写死锁的情况

1.典型死锁场景:转账


假设有用户 1 和用户 2,两人同时互相转账。

死锁产生。

2.解决方案:在代码层进行“ID 排序”


无论谁给谁转账,我们的业务逻辑都强制要求:先锁 ID 小的,再锁 ID 大的。

这样,当事务 A 和事务 B 同时发生时,它们都会先去争抢 id=1 的锁。谁抢到了谁先走,没抢到的就在第一行等着,而不会去占着第二行的锁。这就变“环路等待”为“顺序排队”了。

  • 修改后的逻辑:

    1. 接收到转账请求 (id1=1, id2=2)。

    2. 排序:发现 1 < 2。

    3. 执行 UPDATE ... WHERE id = 1;

    4. 执行 UPDATE ... WHERE id = 2;

http://www.jsqmd.com/news/886609/

相关文章:

  • 告别Cygwin:在Windows 11的WSL2上轻松部署UCSF DOCK 6.11完整环境
  • 探索Windows 11 LTSC系统商店恢复的模块化解决方案:智能部署实战
  • 从Windows API调用到硬盘读写:一次‘读文件’请求的完整I/O栈之旅(含图解)
  • 股票买卖最佳时机:LeetCode121题解
  • 339商业模式介绍(代码)
  • 2026年老面小笼包用面粉哪家品质更稳:批次稳定性、品控标准与耐发酵表现深度解析 - 科技焦点
  • 程序员的自我修养:链接、装载与库(库)
  • VideoDownloadHelper 插件深度解析:Chrome 视频下载架构设计与技术实现
  • 告别抓瞎调试!手把手教你用格西调试精灵搞定IEC60870-5-102协议测试
  • AI圈神秘领袖Ilya一幅画引爆全网,OpenAI三件大事暗示AGI时代将至?
  • TP、FP、FN、TN 详解
  • 一文吃透Linux防火墙:firewalld+SELinux完整防护实操指南
  • 科华UPS电源全品类汇总:选型与场景适配指南
  • HDI与普通PCB的叠层差异
  • 黑客必刷的 23 个网安攻防靶场,零基础到红队全覆盖
  • 【最新】最完美的WPF窗体无边框设计!
  • ETS2LA:为欧洲卡车模拟2打造的智能驾驶辅助系统
  • AI学习 - 大模型基础入门
  • 广州因特智能:AI视觉软硬结合,打破半导体检测装备“卡脖子”困境
  • 如何让PS手柄在Windows上完美运行:DS4Windows终极配置指南
  • Rocky Linux 8.9 虚拟机安装全记录:从ISO下载、SHA256校验到首次登录的完整实操
  • AI时代两大高决策行业的社交营销进化 | 第十届社交媒体风向大会数码家电与汽车分论坛 - 资讯快报
  • 从“DOC/PDF”到“WPS”:细看GJB438C-2021文档格式要求背后的国产化信号与落地指南
  • IEC 61000-4-5
  • 中微单片机SC8F072/SC8P062代码生成工具
  • 【深度解析】Hermes Agent + 多模型 API:构建可持续运行的自主 AI 工作流
  • 自动化程序验证中的智能体证明能力
  • [Dify实战] 团队多人共建 Dify 应用时,哪些资源必须先约定命名、隔离和交接规则?
  • 【AI应用开发工程师】第一章:AI 基础与神经网络入门
  • Airtest Poco实战:5分钟搞定微信小程序自动化测试环境搭建与元素抓取