MySQL 事务的两种使用方式
MySQL 事务的两种使用方式
事务(Transaction)是数据库中一组不可分割的操作单元,遵循 ACID 特性(原子性、一致性、隔离性、持久性)。MySQL 中事务的使用方式主要分为 显式事务 和 隐式事务。
一、显式事务(手动控制事务)
开发者手动定义事务的开始、提交或回滚,适用于需要精确控制多步操作的场景(如转账、订单创建等)。
核心语法
- 开启事务关闭自动提交模式,后续操作进入事务上下文:
START TRANSACTION; -- 推荐使用,清晰明确 -- 或 BEGIN; (功能相同,兼容性略差)
- 执行事务操作执行一系列 SQL 语句(增删改查,其中查询不影响事务状态,但可用于验证):
UPDATE account SET balance = balance - 100 WHERE id = 1; -- A账户减100 UPDATE account SET balance = balance + 100 WHERE id = 2; -- B账户加100
- 提交事务所有操作执行成功后,永久生效:
COMMIT;
- 回滚事务若操作出错,撤销所有已执行的操作,恢复到事务开始前的状态:
ROLLBACK;
- 保存点(可选)在事务中设置中间点,可回滚到指定点(不影响保存点之前的操作):
SAVEPOINT sp1; -- 设置保存点sp1 -- ... 执行部分操作 ... ROLLBACK TO sp1; -- 回滚到sp1,放弃sp1之后的操作
特点
- 需手动控制事务生命周期(开启、提交 / 回滚),灵活性高。
- 适用于多步操作需原子性保证的场景(如 “要么全成功,要么全失败”)。
二、隐式事务(自动提交模式)
MySQL 默认开启 自动提交(AUTOCOMMIT),每条 SQL 语句单独作为一个事务,执行后自动提交,无需手动干预。
核心机制
- 默认状态:SET AUTOCOMMIT = 1;(1 表示开启,0 表示关闭)。
- 每条 SQL 语句执行后立即生效,无法回滚(除非手动关闭自动提交)。
示例
-- 默认AUTOCOMMIT=1,以下语句自动作为单独事务提交 UPDATE account SET balance = 1000 WHERE id = 1; -- 执行后立即生效,无法回滚
特点
- 无需手动管理事务,适合单步操作(如简单的更新、插入)。
- 原子性仅针对单条语句,多步操作无法保证整体一致性(需手动转为显式事务)。
两种方式的对比与注意事项
维度 | 显式事务 | 隐式事务(自动提交) |
控制方式 | 手动开启、提交 / 回滚 | 自动提交,无需手动操作 |
适用场景 | 多步操作需原子性(如转账) | 单步操作(如简单更新) |
回滚能力 | 支持(COMMIT/ROLLBACK) | 不支持(执行后立即生效) |
性能影响 | 长事务可能锁定资源,需谨慎 | 短事务,性能开销小 |
注意事项
- 存储引擎支持:仅 InnoDB 引擎支持事务,MyISAM 等引擎不支持。
- 自动提交开关:显式事务需先关闭自动提交(START TRANSACTION 会自动临时关闭),或手动执行 SET AUTOCOMMIT = 0;。
- 事务隔离级别:需根据业务需求设置(如 READ COMMITTED、REPEATABLE READ 等),默认 REPEATABLE READ。
- 长事务风险:显式事务若长时间未提交 / 回滚,可能导致锁表,影响并发性能。
MySQL 定义了四种标准的事务隔离级别,用于解决并发操作中可能出现的脏读(Dirty Read)、不可重复读(Non-Repeatable Read)、幻读(Phantom Read) 等问题。隔离级别从低到高依次为:
1. 读未提交(READ UNCOMMITTED)
- 定义:一个事务可以读取另一个未提交事务的数据。
- 问题:存在脏读、不可重复读、幻读问题。
- 场景:几乎不使用,仅适用于对数据一致性要求极低的场景。
2. 读已提交(READ COMMITTED)
- 定义:一个事务只能读取另一个已提交事务的数据,避免了脏读。
- 解决:防止脏读。
- 问题:仍可能出现不可重复读、幻读。
- 场景:大多数数据库的默认隔离级别(如 Oracle、SQL Server),适合对数据一致性有一定要求,但允许偶尔不可重复读的场景。
3. 可重复读(REPEATABLE READ)
- 定义:事务开启后,多次读取同一数据的结果始终一致(即使其他事务修改并提交了该数据),避免了不可重复读。
- 解决:防止脏读、不可重复读。
- 问题:理论上可能出现幻读,但 MySQL 通过 MVCC(多版本并发控制) 机制实际避免了幻读。
- 场景:MySQL 的默认隔离级别,适合需要保证多次读取数据一致性的场景(如订单计算)。
4. 串行化(SERIALIZABLE)
- 定义:事务串行执行(类似单线程),完全隔离并发操作。
- 解决:防止脏读、不可重复读、幻读。
- 问题:并发性能极差,可能导致大量超时和锁竞争。
- 场景:仅用于数据一致性要求极高的场景(如金融核心交易)。
隔离级别与并发问题的关系
隔离级别 | 脏读 | 不可重复读 | 幻读 |
读未提交 | 可能 | 可能 | 可能 |
读已提交 | 不可能 | 可能 | 可能 |
可重复读 | 不可能 | 不可能 | 理论可能(MySQL 中不可能) |
串行化 | 不可能 | 不可能 | 不可能 |
如何设置隔离级别
- 会话级别(仅当前连接生效):
SET TRANSACTION ISOLATION LEVEL 隔离级别名称;
示例:SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
- 全局级别(影响所有新连接,现有连接不受影响):
SET GLOBAL TRANSACTION ISOLATION LEVEL 隔离级别名称;
- 查看当前隔离级别:
-- 会话级别 SELECT @@transaction_isolation; -- 全局级别 SELECT @@global.transaction_isolation;
