当前位置: 首页 > 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.zskr.cn/news/1510093.html

相关文章:

  • 讲真的2026年浙江杭州合同纠纷律师 这5家值得推荐 - 本地品牌推荐
  • ECU软件升级背后的守护者:深入解读UDS BootLoader中的安全访问与防变砖机制
  • Kinesalite标签系统:AddTagsToStream和ListTagsForStream使用指南
  • Android Compose基础布局——从传统XML的视角切入了解
  • 填高考志愿这道难题,也有AI参与了
  • 1983-2026年中国人才政策文本数据
  • 仿真轨迹中的高级模式发现与DSL应用
  • 麻省理工学院等机构研究成果揭示博弈学习的新边界
  • 沈阳黄金回收抵押怎么选?2026本地合规办理避坑指南 - 百航
  • 2001-2024年上市公司供应链地理加权距离
  • 2026年上海网约车租赁选购指南:从合规资质到押金透明,一文避坑 - 优质企业观察收录
  • Keyboard Chatter Blocker:如何彻底解决Windows机械键盘连击问题的终极免费方案
  • RVC语音克隆革命:10分钟训练专属AI声音的完整指南
  • 青岛高端珠宝回收避坑红黑榜|权威鉴定!高工价安全回收渠道推荐 - 名奢变现站
  • A2A Python SDK 源码架构解读:一个请求是如何被处理的
  • 天音披露魅族两年亏超34亿,手机停摆后转型车机系统能否自救?
  • 卫生间漏水到楼下怎么查找漏水点?2026随州24小时上门维修电话TOP7机构推荐,免费勘察+精准定位,专业师傅处理屋顶墙体洗手间暗管漏水 - 一修哥咨询
  • 解锁音乐自由:3种方法让你的加密音频文件随处播放
  • 2026年定制化工程塑料采购指南:耐磨pe聚乙烯板材与高强度UPE板材源头厂家对标 - 优质企业观察收录
  • AI新周期下派欧云二次冲击港交所,边缘计算市场谁能拔得头筹?
  • 专业5G仿真平台UERANSIM:构建完整5G网络测试环境的开源解决方案
  • 3种高效方法解决NCM加密音乐格式转换,实现跨平台播放自由
  • 2026山东聊城青少年叛逆教育学校地址汇总!全封闭管教,这几家正规机构家长放心选 - 小途xt
  • 遗传算法工程化实战:从教科书到工业级稳定收敛
  • 别让命名毁了你的流片:Innovus中update_names/changeInstName的隐藏技巧与避坑指南
  • 遗传算法实操三支柱:选择压力、适应度缩放与精英保留
  • 卖包必看!苏州二手名包回收套路揭秘,避开隐形扣费陷阱 - 名奢变现站
  • C++ 智能指针完全指南(三):weak_ptr 与循环引用
  • 深度解析:精油代工 核心工艺与合规生产实践 - 资讯快报
  • 别再只盯着BIOS了!手把手教你用Port 60/64和ASL代码调试笔记本EC(Embedded Controller)