MySQL事务处理是将多个数据库操作封装为一个不可分割的执行单元的机制,所有操作要么全部执行成功,要么全部失败回滚,不会出现部分操作生效的情况,是维护数据一致性的重要手段。

事务的核心特性ACID
MySQL的事务遵循ACID四大特性,这也是事务可靠性的基础:
- 原子性(Atomicity):事务中的所有操作是一个整体,要么全部完成,要么全部不完成,不会停留在中间状态。
- 一致性(Consistency):事务执行前后,数据库的完整性约束没有被破坏,数据符合业务规则。
- 隔离性(Isolation):多个事务同时执行时,一个事务的执行不会被其他事务干扰,每个事务都感觉不到其他事务的存在。
- 持久性(Durability):事务一旦提交,对数据的修改就是永久性的,即使数据库发生故障也不会丢失。
MySQL事务的常用操作
在MySQL中,我们可以通过以下命令控制事务的执行流程:
START TRANSACTION或者BEGIN:开启一个新的事务。COMMIT:提交事务,将事务中的所有操作永久保存到数据库。ROLLBACK:回滚事务,撤销事务中所有未提交的操作,回到事务开启前的状态。SAVEPOINT 保存点名称:在事务中设置一个保存点,后续可以回滚到该保存点,而不是回滚整个事务。ROLLBACK TO 保存点名称:回滚到指定的保存点。
事务使用实战案例
以用户转账场景为例,假设用户A要向用户B转账100元,需要同时完成两个操作:用户A的余额减少100元,用户B的余额增加100元。这两个操作必须同时成功或者同时失败,否则会出现资金对账不一致的问题。
首先创建测试表并插入初始数据:
-- 创建用户余额表
CREATE TABLE user_balance (
user_id INT PRIMARY KEY,
balance DECIMAL(10,2) NOT NULL
);
-- 插入测试数据,用户A余额500,用户B余额300
INSERT INTO user_balance VALUES (1, 500.00), (2, 300.00);
接下来使用事务完成转账操作:
-- 开启事务 START TRANSACTION; -- 用户A余额减少100 UPDATE user_balance SET balance = balance - 100 WHERE user_id = 1; -- 用户B余额增加100 UPDATE user_balance SET balance = balance + 100 WHERE user_id = 2; -- 检查两个操作是否都执行成功,这里可以加业务校验逻辑 -- 如果没有问题,提交事务 COMMIT;
如果在执行过程中出现了异常,比如用户A的余额不足,我们可以回滚事务:
START TRANSACTION; -- 用户A余额减少100 UPDATE user_balance SET balance = balance - 100 WHERE user_id = 1; -- 假设这里发现用户A余额不足,执行回滚 ROLLBACK;
事务的隔离级别
MySQL支持四种事务隔离级别,不同的隔离级别会平衡并发性能和数据一致性,默认隔离级别是可重复读(REPEATABLE READ):
| 隔离级别 | 脏读 | 不可重复读 | 幻读 |
|---|---|---|---|
| 读未提交(READ UNCOMMITTED) | 可能 | 可能 | 可能 |
| 读已提交(READ COMMITTED) | 不可能 | 可能 | 可能 |
| 可重复读(REPEATABLE READ) | 不可能 | 不可能 | 可能(InnoDB通过间隙锁解决) |
| 串行化(SERIALIZABLE) | 不可能 | 不可能 | 不可能 |
可以通过以下命令查看和设置当前会话的事务隔离级别:
-- 查看当前事务隔离级别 SELECT @@transaction_isolation; -- 设置当前会话的隔离级别为读已提交 SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
事务使用注意事项
- 只有InnoDB和NDB存储引擎支持事务,MyISAM存储引擎不支持事务,使用时需要确认表的存储引擎类型。
- 事务中尽量避免执行耗时较长的操作,比如大量的循环计算、外部接口调用等,长时间占用事务会导致锁持有时间变长,影响其他业务的并发性能。
- 不要在事务中执行DDL语句(比如CREATE、ALTER、DROP等),DDL语句会隐式提交当前事务,导致事务无法回滚。
- 合理设置事务的隔离级别,不需要过度追求高隔离级别,避免不必要的性能损耗。