
是思成呀:个人主页
引言
事务之所以能保证数据一致性,核心是靠 ACID 四大特性 "保驾护航"------ 原子性保证操作不可分割,一致性保证数据逻辑无误,隔离性保证多事务互不干扰,持久性保证数据永久保存。而在多事务并发执行时,即使有 ACID,也可能出现脏读、不可重复读、幻读等问题(比如同时给两名高中生缴费导致余额计算错误、查询学生成绩时读到未提交的临时数据)。本文带你吃透 ACID 的底层逻辑,理清并发事务的三大问题,为后续学习隔离级别打下基础!
目录
[1. 原子性(Atomicity)](#1. 原子性(Atomicity))
[2. 一致性(Consistency)](#2. 一致性(Consistency))
[3. 隔离性(Isolation)](#3. 隔离性(Isolation))
[4. 持久性(Durability)](#4. 持久性(Durability))
[1. 脏读(Dirty Read)](#1. 脏读(Dirty Read))
[2. 不可重复读(Non-Repeatable Read)](#2. 不可重复读(Non-Repeatable Read))
[3. 幻读(Phantom Read)](#3. 幻读(Phantom Read))
一、事务的四大特性(ACID)(精简案例解读)
ACID 是事务的核心属性,保证了事务的可靠性和数据一致性,精简后 5 名学生的场景更易理解:
1. 原子性(Atomicity)
- 定义:事务是不可分割的最小操作单元,要么全部执行成功,要么全部失败回滚。
- 案例:高中生缴费事务中,"扣减林墨涵账户余额" 和 "更新缴费状态" 必须同时成功或同时失败,不会出现中间状态(如余额扣了但状态没更)。
- 实现原理:MySQL 通过日志(undo log)记录事务的修改操作,回滚时通过日志撤销已执行的操作。
2. 一致性(Consistency)
- 定义:事务执行前后,数据库的完整性约束(如主键唯一、余额非负)保持不变,数据逻辑一致。
- 案例:林墨涵缴费前账户余额 2000 元 + 缴费记录状态 "未缴费",缴费后余额 500 元 + 状态 "已缴费",整体数据逻辑无矛盾;若出现余额扣了但状态仍为 "未缴费",则违反一致性。
- 关键要求:事务必须满足业务规则(如学生余额不能为负),否则即使原子性满足,一致性也会被破坏。
3. 隔离性(Isolation)
- 定义:多个事务并发执行时,事务之间相互隔离,每个事务感觉不到其他事务的存在。
- 案例:事务 A 给林墨涵缴费(未提交),事务 B 查询林墨涵余额时,不会看到事务 A 未提交的临时数据(余额仍为 2000 元)。
- 实现原理:通过锁机制和多版本并发控制(MVCC)实现,避免并发事务相互干扰。
4. 持久性(Durability)
- 定义:事务一旦提交,对数据的修改会永久保存到数据库(即使服务器崩溃,数据也不会丢失)。
- 实现原理:MySQL 通过 redo log 记录已提交的修改,崩溃恢复时通过 redo log 重新应用修改,保证数据持久化。
- 验证方式:事务提交后,数据会写入磁盘的.ibd 文件(InnoDB 数据文件),重启数据库后林墨涵的余额和缴费状态依然是修改后的值。
二、并发事务引发的三大问题
当多个事务同时操作 5 名高中生数据时,若没有合适的隔离机制,会引发以下核心问题:
1. 脏读(Dirty Read)
- 定义:一个事务读取到另一个事务未提交的数据(临时数据,可能被回滚)。
- 场景演示:
- 事务 A 开启,执行
UPDATE student_account SET balance = 500 WHERE student_name = '林墨涵'(未提交); - 事务 B 查询林墨涵的余额,得到 500 元(脏数据);
- 事务 A 执行
ROLLBACK,林墨涵余额恢复为 2000 元; - 事务 B 读取的 500 元是无效数据,若基于此判断林墨涵余额不足拒绝缴费,就会导致业务错误。
- 危害:基于脏数据的决策会导致业务逻辑错误(如误判高中生缴费能力)。
2. 不可重复读(Non-Repeatable Read)
- 定义:同一事务内多次读取同一数据,结果不一致(其他事务提交了更新操作)。
- 场景演示(精简版):
- 事务 A 开启,首次查询林墨涵余额为 2000 元;
- 事务 B 执行
UPDATE student_account SET balance = 500 WHERE student_name = '林墨涵'并提交; - 事务 A 再次查询林墨涵余额,得到 500 元,与首次结果不一致。
- 与脏读的区别:不可重复读读取的是已提交的数据,脏读读取的是未提交数据。
3. 幻读(Phantom Read)
- 定义:同一事务内多次执行相同的范围查询,结果集的行数不一致(其他事务提交了插入 / 删除操作)。
- 场景演示(精简版):
- 事务 A 开启,查询余额 > 2000 的高中生,得到苏语桐、楚泽宇、温知夏 3 人;
- 事务 B 插入一条新记录:
INSERT INTO student_account(student_name, balance, class_name) VALUES ('江弈辰', 2200, '高一(1)班')并提交; - 事务 A 再次执行相同查询,得到 4 人,行数增加("幻影" 行出现)。
- 与不可重复读的区别:不可重复读针对已有数据的修改(如林墨涵余额变化),幻读针对新数据的插入 / 删除(如新增江弈辰的记录)。
三、问题根源与解决思路
并发事务问题的本质是:多个事务同时操作同一高中生数据,且未对数据访问顺序进行有效控制。解决思路:通过设置事务隔离级别,在 "数据一致性" 和 "并发性能" 之间做权衡 ------ 隔离级别越高,数据越安全,但并发性能越低(比如同时缴费的高中生数量会减少)。
结尾
🍍 我是思成!若这篇内容帮你理清了 MySQL 事务 ACID 特性与并发问题的核心逻辑:
👀 【关注】跟我一起拆解 MySQL 核心知识点,从 ACID 特性到隔离级别,吃透每一个事务并发规则
❤️ 【点赞】让技术干货被更多人看见,让抽象的脏读、幻读逻辑变得易懂
⭐ 【收藏】把 ACID 四大特性、高中生数据并发问题案例存好,事务开发 / 面试时随时查阅
💬 【评论】分享你遇到的高中生数据事务并发问题,或想深挖的事务知识点,一起交流进步
🗳️ 【投票】告诉我你最想拆解的下一个知识点(比如事务隔离级别?锁机制?)
技术学习没有捷径,但找对思路能少走弯路~愿我们都能把抽象的事务特性,转化为可落地的并发控制方案,一步步构建健壮的数据库事务体系!