MySQL 事务处理异常与 ACID 特性详解

拾光
拾光
发布时间:2026-10-15 | 5人浏览过
原创

在开发涉及资金或重要状态流转的应用时,必须保证数据的原子性和一致性。本文将介绍如何通过 SQL 控制 MySQL 事务的执行与回滚,并深入解析事务的 ACID 特性以及并发环境下可能出现的三种典型异常。

1. 模拟转账过程中的事务异常

为了直观展示为什么需要事务控制,我们模拟一个常见的银行转账场景:张三向李四转账 1000 元。在此过程中,如果系统中途发生错误,可能导致资金“凭空产生”或“凭空消失”,破坏数据的一致性。

模拟故障操作:

-- 1. 查询初始余额
select * from account where name = '张三';

-- 2. 张三扣款成功
update account set money = money - 1000 where name = '张三';

-- 假设此处程序出错,导致中断...

-- 3. 此步无法执行,李四未收款
update account set money = money + 1000 where name = '李四';

上述代码中的 “出错了....” 仅为逻辑中断示意。若直接在 MySQL 客户端中连续执行包含非法语法或逻辑错误的语句,前两步的操作可能会被直接提交到数据库(因为 MySQL 默认是自动提交模式)。结果就是:张三的钱被扣了,但李四没有收到钱,这构成了严重的数据不一致。

执行流程示意图如下:

2. 使用 SQL 控制事务执行

为了避免上述风险,我们需要显式地控制事务的边界,即决定何时提交(COMMIT)变更,或在出错时回滚(ROLLBACK)至初始状态。

第 1 步:查看与设置自动提交(不推荐在生产环境直接使用)

MySQL 默认开启 autocommit,意味着每执行一条 DML(增删改)语句都会立即生效。我们可以通过全局会话变量临时关闭它:

-- 查看当前是否自动提交(ON 为 1,OFF 为 0)
SELECT @@autocommit;

-- 关闭自动提交,后续所有操作需手动 COMMIT
SET @@autocommit = 0;
  • 目的:让所有的 UPDATE/INSERT/DELETE 语句处于等待状态,直到收到提交指令。
  • 操作:执行 SET @@autocommit = 0。
  • 完成状态:再次执行 SELECT @@autocommit; 返回结果为 0。
  • 注意:这种方式会影响整个会话的所有连接操作,通常仅用于一次性测试脚本。对于具体的业务交易,建议使用下文的显式事务命令。

第 2 步:显式开启、提交与回滚事务(标准做法)

这是处理具体业务逻辑的标准方式,只针对单次交易流程有效,不影响会话的其他操作。

-- 开启新事务
START TRANSACTION;

或者简写为:BEGIN;

完整的转账事务示例:

-- 1. 开启事务标记
START TRANSACTION;

-- 2. 检查初始余额
SELECT * FROM account WHERE name = '张三';

-- 3. 执行张三扣款
UPDATE account SET money = money - 1000 WHERE name = '张三';

-- 4. 执行李四收款
UPDATE account SET money = money + 1000 WHERE name = '李四';

-- 5. 判断执行结果
-- IF (全步骤成功) THEN 
    COMMIT; -- 将内存中的更改永久写入磁盘
-- END IF;

-- IF (中间步骤报错) THEN 
    ROLLBACK; -- 撤销自 START TRANSACTION 以来所做的所有更改
-- END IF;
  • COMMIT;:将当前事务内的所有数据修改正式持久化到数据库中,结束事务。
  • ROLLBACK;:丢弃当前事务中的所有修改,使数据恢复到执行 START TRANSACTION 之前的状态,相当于“撤销”操作。

3. 事务的四大特性(ACID)

事务机制之所以能保证数据的高可用性,归功于其四个核心特性,简称 ACID:

  1. 原子性(Atomicity):事务是一个不可分割的最小工作单位,事务中的操作要么全部成功,要么全部失败(回滚),不允许部分执行。
  2. 一致性(Consistency):事务开始前和结束后,数据库的完整性约束没有被破坏。例如转账后,账户总和应保持不变。
  3. 隔离性(Isolation):多个用户并发访问数据库时,数据库为每个用户开启的事务不被其他事务干扰。各并发事务之间相互独立。
  4. 持久性(Durability):事务一旦提交,其对数据库的修改就是永久的,即使之后发生系统崩溃,数据也不会丢失。

4. 补充:MySQL 事务并发处理的三种异常

当多个事务同时运行时,由于缺乏适当的隔离机制,可能会引发以下三种典型的读取异常:

4.1 脏读 (Dirty Read)

定义:事务 A 读取了事务 B 更新但尚未提交的数据。如果 B 随后回滚,那么 A 读取到的数据就是无效的(“脏”)。

场景:A1 开始事务修改某记录,但未提交;此时 A2 也开启事务读取该记录,拿到了 A1 的结果。若 A1 后来回滚了,A2 拿到的就是一个从未存在过的值。

4.2 不可重复读 (Non-repeatable Read)

定义:在同一事务内,两次读取同一条记录的结果不一致。通常是因为另一个事务 修改(Update) 或删除了该数据并提交。

场景:A2 在事务开始时查询 id=1 的记录值为 100;此时 A1 更新了 id=1 的值变为 200 并提交;A2 再次查询 id=1,发现变成了 200,导致前后读取结果不同。

4.3 幻读 (Phantom Read)

定义:在同一事务内,两次查询相同范围的记录集,行数不一样。通常是因为另一个事务在该范围内新增(Insert)了一条数据并提交。

场景:A2 查询表中有 10 条符合条件的数据;此时 A1 插入了一条新的符合该条件的数据并提交;A2 再次查询,发现有了 11 条数据,仿佛发生了“幻觉”。

总结:以上是关于 MySQL 基础教程之事务异常情况的内容详细介绍,更多关于 MySQL 事务管理与并发控制的资料,请关注本站其它相关文章!

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表