MySQL 事务详解
MySQL 事务详解
- 一、事务是什么?
- 为什么需要事务?
- 二、事务的四大特性(ACID)
- 举例说明:转账操作
- 三、MySQL 中事务的支持
- 四、事务分类:隐式 vs 显式
- 1. 隐式事务(自动提交)
- 2. 显式事务(手动控制)
- 五、事务的操作语句
- 使用保存点(SAVEPOINT)
- 六、并发事务带来的问题
- 七、事务隔离级别
- 八、InnoDB 如何实现事务
- 1. 重做日志(Redo Log)
- 2. 撤销日志(Undo Log)
- 3. MVCC(多版本并发控制)
- 九、最佳实践与注意事项
- 十、总结
一、事务是什么?
在数据库系统中,事务(Transaction)
是指一组操作序列,这些操作要么全部执行成功,要么全部不执行,是数据库操作的基本单位,主要用于保证数据的一致性和完整性。
为什么需要事务?
在多个 SQL 操作依赖于彼此时,若某条操作失败,必须撤销之前的操作以防止数据不一致。例如:
UPDATE account SET balance = balance - 100 WHERE user = 'A';
UPDATE account SET balance = balance + 100 WHERE user = 'B';
如果第二条语句失败,而第一条已经生效,就会导致数据不一致。事务机制可以确保这种情况不会发生。
二、事务的四大特性(ACID)
特性 | 含义 |
---|---|
原子性(Atomicity) | 事务中的所有操作要么全部成功,要么全部失败,不会停留在中间状态。 |
一致性(Consistency) | 事务前后数据库保持一致状态,不会因事务失败造成数据损坏。 |
隔离性(Isolation) | 并发事务之间互不干扰,每个事务的执行不会被其他事务看到。 |
持久性(Durability) | 一旦事务提交成功,结果将永久保存到数据库,即使系统崩溃也不丢失。 |
举例说明:转账操作
步骤 | 操作 | 说明 |
---|---|---|
1 | A账户减100元 | 原子性的一部分 |
2 | B账户加100元 | 必须与上一步一同成功 |
3 | 事务提交 | 所有变更永久保存 |
❌ | 若第2步失败,事务回滚 | 保证一致性、原子性 |
三、MySQL 中事务的支持
不是所有存储引擎都支持事务,常见如下:
存储引擎 | 是否支持事务 | 是否支持外键 |
---|---|---|
InnoDB | ✅ | ✅ |
MyISAM | ❌ | ❌ |
MEMORY | ❌ | ❌ |
TokuDB | ✅ | ✅ |
查看支持情况:
SHOW ENGINES;
四、事务分类:隐式 vs 显式
1. 隐式事务(自动提交)
MySQL 默认自动提交每一条 DML 语句:
UPDATE users SET age = 30 WHERE id = 1; -- 自动提交
2. 显式事务(手动控制)
当需要将多条语句当作一个整体执行时,使用显式事务:
SET autocommit = 0; -- 禁用自动提交
START TRANSACTION;
UPDATE users SET balance = balance - 100 WHERE name = 'A';
UPDATE users SET balance = balance + 100 WHERE name = 'B';
COMMIT; -- 提交事务
-- ROLLBACK; -- 取消事务
推荐使用
BEGIN
作为START TRANSACTION
的简洁写法。
五、事务的操作语句
语句 | 含义 |
---|---|
START TRANSACTION / BEGIN | 显式开启事务 |
COMMIT | 提交事务,持久保存变更 |
ROLLBACK | 回滚事务,撤销变更 |
SAVEPOINT | 设置事务保存点(用于局部回滚) |
ROLLBACK TO SAVEPOINT | 回滚到某个保存点 |
使用保存点(SAVEPOINT)
START TRANSACTION;
UPDATE t SET score = 90 WHERE id = 1;
SAVEPOINT sp1;
UPDATE t SET score = 100 WHERE id = 1;
ROLLBACK TO sp1; -- 回滚到sp1,score回到90
COMMIT;
六、并发事务带来的问题
在并发执行多个事务时,若没有合理控制,会产生以下问题:
并发问题 | 描述 |
---|---|
脏读 | 读到未提交事务修改的数据 |
不可重复读 | 同一事务两次读到不同数据 |
幻读 | 同一查询两次返回行数不同(新增/删除行) |
七、事务隔离级别
事务的隔离级别定义了事务间可见的数据范围,MySQL 支持如下四种:
隔离级别 | 描述 | 能否避免并发问题 |
---|---|---|
READ UNCOMMITTED | 允许读未提交的数据(最低) | ❌脏读、不可重复读、幻读 |
READ COMMITTED | 只能读已提交的数据 | ✅脏读 ❌不可重复读、幻读 |
REPEATABLE READ | 可重复读(MySQL 默认) | ✅脏读 ✅不可重复读 ❌幻读 |
SERIALIZABLE | 串行执行(最高隔离) | ✅全部避免,但性能最低 |
设置隔离级别:
-- 查询当前隔离级别
SELECT @@transaction_isolation;-- 修改隔离级别(会话级)
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
八、InnoDB 如何实现事务
InnoDB 使用以下机制来支持事务:
1. 重做日志(Redo Log)
用于保证持久性,即使崩溃后也能恢复事务提交的结果。
2. 撤销日志(Undo Log)
用于支持原子性和一致性。当事务回滚时,Undo Log 可以撤销操作。
3. MVCC(多版本并发控制)
实现事务的隔离性(特别是可重复读),通过版本控制每一行数据,允许事务读到历史版本数据。
九、最佳实践与注意事项
- 显式开启事务时,要显式
COMMIT
或ROLLBACK
,否则锁会长期占用。 - 控制事务作用域,不要将事务保持过长时间。
- 多个事务同时操作数据时要注意锁竞争与死锁问题。
- 尽量使用合适的隔离级别以提升性能。
- 结合业务需求设置合适的回滚点
SAVEPOINT
。
十、总结
MySQL 事务机制是保证数据一致性、完整性的重要基础。掌握事务的使用方法、隔离级别、InnoDB 实现原理,以及并发控制策略,是每位开发者和 DBA 的必备技能。