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

MySQL 数据库事务


一、事务基础

1. 什么是事务?

事务(Transaction)是一组 SQL 语句的逻辑执行单元,这组操作要么全部成功执行,要么全部失败回滚,不会出现部分执行、部分失败的中间状态。

经典场景:银行转账

  • 张三给李四转 100 元,需要执行两个操作:
    1. UPDATE bank_account SET balance = balance - 100 WHERE name = '张三';
    2. UPDATE bank_account SET balance = balance + 100 WHERE name = '李四';
  • 这两个操作必须作为一个整体:要么都成功,要么都失败,否则会出现张三余额减少但李四余额未增加的异常。

2. 事务的核心目标

在事务执行过程中,必须保证以下四点(即事务的ACID 特性):

  1. 原子性 (Atomicity):操作要么全成,要么全败。
  2. 一致性 (Consistency):事务前后数据的完整性不被破坏。
  3. 隔离性 (Isolation):多个事务并发执行时互不干扰。
  4. 持久性 (Durability):事务提交后,数据修改永久保存到磁盘,即使数据库崩溃也不会丢失。

二、事务的 ACID 特性(面试核心)

1. 原子性 (Atomicity)

  • 定义:一个事务中的所有操作,要么全部执行成功,要么全部执行失败,不会出现部分执行的情况。
  • 实现机制:通过回滚 (Rollback)保证。如果事务执行过程中发生错误(如服务器宕机、SQL 异常),数据库会将数据恢复到事务开始前的状态,就像这个事务从未执行过一样。
  • 关键操作ROLLBACK语句用于手动回滚事务。

2. 一致性 (Consistency)

  • 定义:事务执行前后,数据库的完整性约束(如数据总和、业务规则)不会被破坏,数据始终符合预期。
  • 例子:转账前张三 + 李四余额总和是 2000,转账后也必须是 2000(900 + 1100),不能变成 1900。
  • 实现机制
    • 数据库层面:通过约束(非空、唯一、外键等)保证。
    • 故障恢复层面:通过重做日志 (Redo Log)回滚日志 (Undo Log)保证事务执行过程中服务器宕机后的数据一致性。

3. 隔离性 (Isolation)

  • 定义:多个并发事务同时对数据进行读写时,彼此之间相互隔离,一个事务的执行不会影响其他事务。
  • 核心问题:并发事务会带来数据不一致问题,需要通过隔离级别安全性性能之间做权衡。
  • 实现机制:通过锁机制(行锁、表锁)和 MVCC(多版本并发控制)实现不同的隔离级别。

4. 持久性 (Durability)

  • 定义:事务一旦提交(COMMIT),对数据的修改就会永久保存到磁盘,即使数据库服务器崩溃、操作系统崩溃或断电,数据也不会丢失。
  • 实现机制
    • 事务提交时,修改会先写入重做日志 (Redo Log)并持久化到磁盘。
    • 即使数据库宕机重启,也会通过 Redo Log 恢复已提交的事务数据。

三、事务的基本操作

1. 查看支持事务的存储引擎

SHOW ENGINES;
  • InnoDB:MySQL 默认存储引擎,完整支持事务,是生产环境的首选。
  • MyISAM、MEMORY 等引擎不支持事务,只适合只读场景。

2. 事务控制语法

2.1 开启事务
-- 方式一:标准语法 START TRANSACTION; -- 方式二:简写,与 START TRANSACTION 等价 BEGIN; -- 方式三:BEGIN WORK,与 BEGIN 等价 BEGIN WORK;

开启事务后,MySQL 会自动关闭自动提交 (autocommit),后续的修改操作需要手动COMMITROLLBACK

2.2 提交事务
-- 提交事务,将修改永久保存到磁盘 COMMIT;
  • 提交后,事务结束,数据修改对其他事务可见。
2.3 回滚事务
-- 回滚事务,撤销所有未提交的修改 ROLLBACK;
  • 回滚后,事务结束,数据恢复到事务开始前的状态。

3. 自动提交与手动提交

3.1 查看自动提交状态
SHOW VARIABLES LIKE 'autocommit';
  • ON:默认值,自动提交事务,单条 DML(INSERT/UPDATE/DELETE)执行后会自动提交。
  • OFF:手动提交,所有修改必须显式调用COMMIT才会持久化。
3.2 修改自动提交
-- 开启自动提交 SET AUTOCOMMIT = 1; -- 或 SET AUTOCOMMIT = ON; -- 关闭自动提交 SET AUTOCOMMIT = 0; -- 或 SET AUTOCOMMIT = OFF;

⚠️ 注意:手动开启START TRANSACTIONBEGIN时,会临时覆盖autocommit设置,必须手动COMMIT/ROLLBACK结束事务。

4. 保存点 (Savepoint)

保存点用于在事务内部设置还原点,可以将事务回滚到指定保存点,而不是回滚整个事务。

4.1 语法
-- 1. 开启事务 START TRANSACTION; -- 2. 执行 SQL 操作... -- 3. 设置保存点 SAVEPOINT savepoint_name; -- 4. 继续执行 SQL 操作... -- 5. 回滚到指定保存点 ROLLBACK TO savepoint_name; -- 6. 提交或回滚整个事务 COMMIT; -- 或 ROLLBACK;
4.2 示例
START TRANSACTION; -- 操作1:张三余额减100 UPDATE bank_account SET balance = balance - 100 WHERE name = '张三'; SAVEPOINT sp1; -- 设置保存点sp1 -- 操作2:李四余额加100 UPDATE bank_account SET balance = balance + 100 WHERE name = '李四'; SAVEPOINT sp2; -- 设置保存点sp2 -- 操作3:新增王五账户 INSERT INTO bank_account VALUES (3, '王五', 5000); -- 回滚到sp1,撤销操作2和操作3,保留操作1 ROLLBACK TO sp1; COMMIT; -- 最终只保留张三余额减100的操作

四、事务的隔离性与隔离级别

1. 并发事务带来的问题

多个事务并发执行时,会出现以下三种数据不一致问题:

表格

问题定义场景
脏读 (Dirty Read)一个事务读取到了另一个事务未提交的数据事务 A 修改了数据但未提交,事务 B 就读到了这个修改值,若 A 回滚,B 读到的数据就是脏数据
不可重复读 (Non-repeatable Read)同一个事务内,两次相同条件查询得到的结果不一致事务 A 第一次查询得到数据 X,事务 B 修改了 X 并提交,事务 A 再次查询得到了不同的数据
幻读 (Phantom Read)同一个事务内,两次范围查询得到的记录数不一致事务 A 第一次查询得到 10 条记录,事务 B 插入了新记录并提交,事务 A 再次查询得到 11 条记录

2. 四种隔离级别

MySQL InnoDB 支持四种隔离级别,从低到高依次为:

表格

隔离级别脏读不可重复读幻读特点
READ UNCOMMITTED (读未提交)❌ 存在❌ 存在❌ 存在隔离性最低,性能最高,几乎不用
READ COMMITTED (读已提交)✅ 解决❌ 存在❌ 存在Oracle、SQL Server 默认级别,避免脏读
REPEATABLE READ (可重复读)✅ 解决✅ 解决⚠️ 部分解决MySQL InnoDB 默认级别,通过 MVCC 解决不可重复读,通过 Next-Key Lock 解决大部分幻读
SERIALIZABLE (串行化)✅ 解决✅ 解决✅ 解决隔离性最高,性能最差,完全串行执行,避免所有并发问题

3. 隔离级别详解

3.1 READ UNCOMMITTED(读未提交)
  • 问题:允许事务读取其他事务未提交的数据,会出现脏读、不可重复读、幻读
  • 场景:几乎不使用,仅用于理论演示。
3.2 READ COMMITTED(读已提交)
  • 解决脏读,事务只能读取其他事务已提交的数据。
  • 存在不可重复读、幻读
  • 设置语句
    SET GLOBAL TRANSACTION ISOLATION LEVEL READ COMMITTED; SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
3.3 REPEATABLE READ(可重复读)
  • 解决脏读、不可重复读,同一个事务内多次查询结果一致。
  • 存在部分幻读,MySQL 通过Next-Key Lock(间隙锁 + 行锁)机制,在一定程度上避免了幻读。
  • 设置语句
    SET GLOBAL TRANSACTION ISOLATION LEVEL REPEATABLE READ; SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
  • 核心实现:InnoDB 的 MVCC(多版本并发控制)为每个事务生成数据快照,保证事务期间读到的数据是一致的。
3.4 SERIALIZABLE(串行化)
  • 解决所有并发问题,强制事务串行执行,完全避免竞争。
  • 缺点:性能极差,并发能力几乎为零,仅用于对数据一致性要求极高的场景(如金融核心系统)。
  • 设置语句
    SET GLOBAL TRANSACTION ISOLATION LEVEL SERIALIZABLE; SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;

4. 查看与设置隔离级别

4.1 查看当前隔离级别
-- 查看全局隔离级别 SELECT @@GLOBAL.transaction_isolation; -- 查看当前会话隔离级别 SELECT @@SESSION.transaction_isolation;
4.2 设置隔离级别
-- 方式一:设置全局(所有新连接生效) SET GLOBAL TRANSACTION ISOLATION LEVEL [LEVEL]; -- 方式二:设置当前会话(仅当前连接生效) SET SESSION TRANSACTION ISOLATION LEVEL [LEVEL];

[LEVEL]可替换为:READ UNCOMMITTED/READ COMMITTED/REPEATABLE READ/SERIALIZABLE


五、事务的底层实现(补充)

1. MVCC(多版本并发控制)

  • 作用:在REPEATABLE READ隔离级别下,实现读写不阻塞,提升并发性能。
  • 原理
    • 为每行数据保存多个版本,事务读取时选择合适的版本(快照)。
    • 通过undo log保存历史版本,通过read view决定可见版本。
  • 优势:读操作不加锁,写操作只加行锁,大幅提升并发读写性能。

2. 锁机制

  • 行锁 (Row Lock):锁定单行数据,并发粒度最小,性能最高。
  • 间隙锁 (Gap Lock):锁定索引间隙,防止其他事务在间隙中插入数据,避免幻读。
  • Next-Key Lock:行锁 + 间隙锁,是 InnoDB 在REPEATABLE READ隔离级别下避免幻读的核心手段。
  • 表锁 (Table Lock):锁定整张表,并发粒度最大,性能最差,仅用于 DDL 操作。

六、事务使用最佳实践

  1. 事务要短小:避免长事务(如事务执行时间超过几秒),长事务会占用锁资源,导致其他事务阻塞,甚至引发死锁。
  2. 避免在事务中执行无关操作:如网络请求、IO 操作,这些操作会延长事务执行时间,增加锁竞争。
  3. 选择合适的隔离级别
    • 普通业务:使用 MySQL 默认的REPEATABLE READ
    • 对一致性要求极高的金融场景:可考虑SERIALIZABLE
    • 读多写少、对一致性要求不高的场景:可使用READ COMMITTED提升性能。
  4. 显式控制事务边界:不要依赖autocommit,在业务代码中显式使用BEGIN/COMMIT/ROLLBACK,保证事务逻辑清晰。
  5. 谨慎使用保存点:保存点会增加事务复杂度,仅在需要部分回滚的场景下使用。
  6. 处理事务异常:在代码中捕获异常,异常发生时必须ROLLBACK,避免数据不一致。

七、事务面试高频考点

  1. 事务的 ACID 特性是什么?分别怎么实现?
  2. 并发事务会带来哪些问题?对应的隔离级别是什么?
  3. MySQL InnoDB 默认的隔离级别是什么?怎么解决幻读?
  4. 什么是 MVCC?它的作用是什么?
  5. 什么是脏读、不可重复读、幻读?分别怎么解决?
  6. 事务的提交和回滚有什么区别?
  7. 什么是自动提交?如何关闭自动提交?
http://www.jsqmd.com/news/998329/

相关文章:

  • 一些可能需要的skill支持参考资料
  • FPGA工程师的硬件思维课:从IIC总线的“线与”特性,彻底搞懂为什么必须加上拉电阻和开漏输出
  • 告别焊球!用混合键合(Hybrid Bonding)给芯片“叠罗汉”,性能翻倍的秘密
  • 指针式仪表图像自动读数方案:OpenCV预处理+k-means刻度分割+角度映射
  • 2026宝鸡出手黄金铂金白银回收避坑指南 5 家经营多年实体回收门店走访测评 + 详细地址(更新时间:2026-06-12_11:10:26) - 中业金奢再生回收中心
  • 2026杭州搬家公司推荐 适配全场景需求指南 - 资讯快报
  • Windows下开箱即用的CTF解题工具包,带猪圈密码图解和插件热加载功能
  • 计算机毕业设计之计算机网络题库平台设计与实现
  • 2000-2024年新闻文本数据
  • 对数正态分布:乘性过程下非负右偏数据的天然建模语言
  • FPGA可用的128位AES加密Verilog代码包,含S盒与密钥扩展模块
  • 2026宁波标识设计公司评测:多维度对比甄选优质服务商 - 奔跑123
  • FastAPI-Backend-Template完全指南:如何用FastAPI+PostgreSQL构建高性能异步后端
  • ECU软件升级背后的守护者:深入解读UDS BootLoader中的安全访问与防变砖机制
  • 讲真的2026年浙江杭州合同纠纷律师 这5家值得推荐 - 本地品牌推荐
  • 医用超声图像模拟系统:教学模块设计与实现
  • 微信投票小程序哪个好?2026最新实测防刷排名|火星投票永久免费零广告 - 微信投票小程序
  • MSPM0G3507上跑通JY60陀螺仪:带欧拉角解算的CCS Theia可运行工程
  • 深蓝词库转换器:终极开源词库转换解决方案
  • 2026年重庆西南铝铝材深度评测:汽车轻量化与工业应用选型指南 - 新闻快传
  • 别死记硬背!用‘乐高积木’思维理解递归:从分数求和到GCD的生动比喻
  • Memoria 全新功能上线:借助记忆分支与协作空间,像协作代码一样协作 Agent 记忆
  • 填高考志愿这道难题,也有AI参与了
  • Kinesalite标签系统:AddTagsToStream和ListTagsForStream使用指南
  • Android Compose基础布局——从传统XML的视角切入了解
  • 别再硬解析了!手把手教你用Python搞定TLV/BER/DER协议数据(附完整代码)
  • 1983-2026年中国人才政策文本数据
  • 麻省理工学院等机构研究成果揭示博弈学习的新边界
  • Prophet外部变量实战指南:从选型、编码到归因的全流程避坑
  • MusicFree插件开发完全指南:三分钟构建跨平台音乐聚合应用