MySQL 事务详解:从转账场景到 ACID 特性与隔离级别

蓝鲸
蓝鲸
发布时间:2026-10-15| 6人浏览过
原创

在涉及资金变动或多步操作的业务中,如何确保数据绝对安全?本文以银行转账为例,拆解 MySQL 事务(Transaction)的核心机制,涵盖开启与提交流程、ACID 四大特性原理,以及四种隔离级别对脏读、不可重复读和幻读等并发问题的解决方案。

结果或目标:理解事务的业务价值

数据库中,事务(Transaction)可以将多个 SQL 语句打包为一个整体执行单元。其核心意义在于保证操作的完整性:事务中的所有操作要么全部成功执行,要么完全不执行,从而避免中途因系统故障或逻辑错误导致的数据不一致。

典型场景:账户转账
张三向李四转账 2000 元,这在数据库层面包含两个紧密关联的操作:

  1. 扣除张三账户余额 2000 元;
  2. 增加李四账户余额 2000 元。

若这两步操作未作为事务处理,一旦第一步执行成功而第二步失败,将导致张三资产损失且李四未受益。使用事务可确保两者同进同退,维护数据最终状态的正确性。

准备条件:环境搭建与数据初始化

在演示事务操作前,需准备好基础表结构。以下 SQL 创建一个账户表并写入初始测试数据:

-- 创建账户表
CREATE TABLE account(
     id INT PRIMARY KEY AUTO_INCREMENT,
     name VARCHAR(20),
     money DOUBLE(10,2)
);

-- 初始化测试数据:张三和李四各拥有 10000 元
INSERT INTO account(name, money) VALUES ('张三', 10000), ('李四', 10000);

真实操作顺序:开启、提交与回滚事务

第 1 步:开启事务

目的:告诉 MySQL 引擎接下来的多条 SQL 属于同一个逻辑单元,在正式提交前暂不永久修改磁盘数据。
入口/命令:在 MySQL 命令行客户端输入 START TRANSACTION;。
效果:此时会话处于自动提交模式关闭状态。

第 2 步:执行业务 SQL

动作:编写符合业务逻辑的增删改查语句。
重要参数/示例:执行转账扣款与入账操作。
注意:在 COMMIT 之前,这些变更在当前用户的会话中可见,但其他独立会话通常无法看到未提交的变更(取决于隔离级别),且数据尚未落盘。

-- 开启事务后执行转账
START TRANSACTION;
UPDATE account SET money = money - 2000 WHERE name = '张三';
UPDATE account SET money = money + 2000 WHERE name = '李四';

第 3 步:判断结果并提交或回滚

完成判断检查上一步 SQL 返回的状态或业务逻辑是否无误。
选择一:提交(Commit)。如果一切正常,使用 COMMIT; 将临时变更写入硬盘,事务结束。此后数据永久生效。
选择二:回滚(Rollback)。如果在执行过程中发现错误(如 SQL 语法错误或业务校验失败),使用 ROLLBACK;。这将利用 Undo Log 撤销当前事务中所有已做的更改,使数据回到 START TRANSACTION 之前的状态。

异常情况演示:触发回滚

假设在执行第二条更新语句时故意插入错误 SQL(模拟异常中断),观察事务保护机制:

-- 重置数据为初始状态以确保演示准确
UPDATE account SET money = 10000 WHERE name IN ('张三', '李四');

START TRANSACTION;
-- 正常扣款张三
UPDATE account SET money = money - 2000 WHERE name = '张三';
-- 模拟语法错误的第二句 SQL
SELECT 1;' -- ERROR 1064 (42000): You have an error in your SQL syntax...

-- 由于上一条报错,事务链断裂或未正确提交,我们需要手动查看并处理
SELECT * FROM account;
-- 此时张三减了钱,李四没加钱,数据不一致。需要回滚修复。
ROLLBACK;
SELECT * FROM account;
-- 查询结果:两人余额均恢复为 10000.00
-- 正确的完整提交流程示例
START TRANSACTION;
UPDATE account SET money = money - 2000 WHERE name = '张三';
UPDATE account SET money = money + 2000 WHERE name = '李四';
COMMIT;-- 验证数据已变
SELECT * FROM account;

原文有依据的排错与注意事项

  • 备份提醒:在生产环境中进行 ROLLBACK 或大规模事务操作前,建议先备份相关表或开启自动存档,以防误操作。
  • 开销限制:虽然事务能防止错误,但“回滚”本身有计算开销。Undo Log 记录了逆操作,当数据量极大时,频繁的大事务回滚会消耗大量 CPU 和 I/O 资源。
  • 物理删除风险:事务不能“起死回生”。如果已经 COMMIT 并触发了后续依赖该数据的级联逻辑,或者通过 DDL 语句删除了表结构,简单的 ROLLBACK 往往无法完全恢复现场。

技术原理:ACID 四大特性

1. 原子性(Atomicity)

事务是不可分割的最小工作单元。它依赖 undo log(回滚日志)。InnoDB 会在修改数据时生成反向操作日志,若发生错误或主动回滚,引擎读取 undo log 将数据还原到事务开始前。

2. 一致性(Consistency)

事务执行前后,数据库必须处于合法状态。例如转账总额不变,或受唯一索引约束的记录不被破坏。原子性是手段,一致性是最终目标。

3. 隔离性(Isolation)

多用户并发访问时,事务之间互不干扰。这是最容易产生问题的环节,需要通过隔离级别控制锁或 MVCC(多版本并发控制)来解决。

4. 持久性(Durability)

一旦 COMMIT,数据修改将永久保存,即使数据库宕机、断电也能恢复。这主要依靠 redo log(重做日志)支持。InnoDB 采用 WAL(Write-Ahead Logging)策略,先将变更日志落盘,再修改内存页,从而保障崩溃后的数据找回。

进阶挑战:事务并发异常与隔离级别

在高并发环境下,缺乏隔离会导致以下三种常见数据异常。解决思路通常是:提高隔离性会降低并发效率,降低隔离性则提升速度但牺牲准确性。

1. 脏读(Dirty Read)

现象:事务 A 修改了数据但未提交,事务 B 读取到了该未提交的数据。若 A 随后回滚,B 读到的就是无效数据。
类比:张三正在写代码未发布,李四直接看了张三未写完的代码。

2. 不可重复读(Unrepeatable Read)

现象:同一事务中,多次读取同一字段得到的值不同。原因是事务 A 读取期间,事务 B 修改并提交了该记录。
类比:李四读代码时,张三修改了代码内容并提交,导致李四读到的中途变了。

3. 幻读(Phantom Read)

现象:同一事务中,两次范围查询(如 SELECT ... WHERE)返回的行数或集合不同。原因是事务 A 查询期间,事务 B 插入了新行并提交了。
类比:李四统计文件数量时,张三新增或删除了一个无关文件,导致总数对不上。

MySQL 的四个隔离级别

MySQL 提供四种标准隔离级别(默认设置为 Repeatable Read),用于解决上述问题:

脏读 不可重复读 幻读
Read Uncommitted(读未提交) √ √ √
Read Committed(读已提交) × √ √
Repeatable Read(可重复读)- MySQL 默认 × × √*
Serializable(串行化) × × ×

解读:

  • Read Uncommitted:几乎无限制,性能最高但最不安全,生产环境极少使用。
  • Read Committed:Oracle 默认级别。解决了脏读,但允许不可重复读。
  • Repeatable Read:解决了脏读和不可重复读。在 InnoDB 实现中,配合 Next-Key Lock 机制,通常也能在一定程度上避免幻读(但在特定非一致性快照读场景下仍可能存在差异)。
  • Serializable:强制事务串行执行,彻底杜绝并发异常,但性能代价巨大,仅适用于极低并发且强一致性的核心金融场景。

应用建议:对于大多数 Web 应用(如点赞数、浏览量),容忍轻微的不一致性以提升响应速度即可;但对于银行账户交易等场景,建议严格校验并使用合适的隔离级别甚至悲观锁来确保绝对准确。

简要总结

事务是数据库维护数据一致性的基石。掌握 START TRANSACTION、COMMIT 和 ROLLBACK 的使用时机,理解 ACID 特性背后的 undo/redo log 支撑,并根据业务对读写性能和数据准确性的权衡选择合适的隔离级别,是 MySQL 开发中的关键能力。

以上就是 MySQL 学习之事务详解的详细内容,更多关于 MySQL 事务隔离级别与事务处理的资料请关注本站其它相关文章!

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。