一、什么是事务?
定义:
事务是数据库中一组不可分割的操作,这些操作要么全部成功,要么全部失败。
关键词:
原子性
例如:
银行转账:
张三给李四转 100 元。
需要两个操作:
SQL 1:
张三余额减少:
UPDATE account SET money = money - 100 WHERE name='张三';SQL 2:
李四余额增加:
UPDATE account SET money = money + 100 WHERE name='李四';正常:
张三 -100 李四 +100完成。
但是如果:
第一条成功:
张三 -100第二条失败:
李四 +0结果:
钱消失了这是绝对不能接受的。
事务保证:
两个操作: 成功: 一起提交 失败: 全部撤销二、事务的基本流程
事务通常:
开启事务 ↓ 执行SQL ↓ 提交 COMMIT 或者 ↓ 回滚 ROLLBACK三、MySQL事务基本语法
开启事务
START TRANSACTION;或者:
BEGIN;执行操作:
UPDATE account SET money = money - 100 WHERE id=1;提交:
COMMIT;数据永久保存。
回滚:
ROLLBACK;撤销之前操作。
四、事务案例
假设:
账户表:
| id | name | money |
|---|---|---|
| 1 | 张三 | 1000 |
| 2 | 李四 | 500 |
开始:
START TRANSACTION;扣钱:
UPDATE account SET money=money-100 WHERE id=1;加钱:
UPDATE account SET money=money+100 WHERE id=2;成功:
COMMIT;结果:
| name | money |
|---|---|
| 张三 | 900 |
| 李四 | 600 |
如果第二步失败:
ROLLBACK;恢复:
| name | money |
|---|---|
| 张三 | 1000 |
| 李四 | 500 |
五、事务四大特性 ACID ⭐⭐⭐⭐⭐
这是面试重点。
ACID:
A Atomicity C Consistency I Isolation D Durability1. Atomicity(原子性)
含义:
事务中的操作不可分割,要么全部成功,要么全部失败。
例如:
转账:
扣钱 + 加钱不能只完成一半。
对应:
ROLLBACK2. Consistency(一致性)
含义:
事务执行前后,数据库的数据必须保持正确状态。
例如:
转账前:
总金额: 1500转账后:
900 + 600 = 1500总金额不变。
一致性是最终目标。
3. Isolation(隔离性)
含义:
多个事务同时执行时,不能互相干扰。
例如:
两个用户同时修改订单。
事务A:
修改订单状态事务B:
读取订单状态不能看到中间状态。
通过:
锁机制
和:
隔离级别
实现。
4. Durability(持久性)
含义:
事务提交后,数据永久保存。
例如:
执行:
COMMIT;然后服务器重启。
数据仍然存在。
MySQL通过:
- redo log
- 磁盘持久化
保证。
六、为什么需要事务?
没有事务:
例如订单创建:
需要:
- 创建订单
INSERT order;- 扣库存
UPDATE product;- 扣余额
UPDATE account;如果:
订单成功:
库存失败:
结果:
订单存在 库存没减少 钱没扣业务错误。
使用事务:
订单 库存 余额 三个操作: 一起成功 或者一起失败七、事务提交方式
MySQL 默认:
autocommit=1;表示:
自动提交。
例如:
执行:
UPDATE user SET name='Tom' WHERE id=1;立即生效。
查看:
SHOW VARIABLES LIKE 'autocommit';关闭:
SET autocommit=0;之后:
需要:
COMMIT;才保存。
八、事务隔离级别 ⭐⭐⭐⭐⭐
多个事务同时执行,会产生问题:
问题1:脏读
问题2:不可重复读
问题3:幻读
为了解决这些问题:
数据库提供隔离级别。
MySQL 有四种:
| 隔离级别 | 说明 |
|---|---|
| READ UNCOMMITTED | 读未提交 |
| READ COMMITTED | 读已提交 |
| REPEATABLE READ | 可重复读 |
| SERIALIZABLE | 串行化 |
九、查看当前隔离级别
MySQL 8:
SELECT @@transaction_isolation;通常:
InnoDB 默认:
REPEATABLE READ十、三种并发问题
1. 脏读(Dirty Read)
定义:
一个事务读取到了另一个事务未提交的数据。
例如:
事务A:
修改余额1000→500未提交。
事务B:
读取:
500事务A:
回滚:
1000事务B读取了不存在的数据。
这就是脏读。
2. 不可重复读
定义:
同一个事务中,两次读取同一数据,结果不同。
例如:
事务A:
第一次查询:
余额1000事务B:
修改:
余额500提交。
事务A:
再次查询:
余额500两次结果不同。
3. 幻读
定义:
一个事务读取时,发现多了一些不存在的数据。
例如:
事务A:
查询:
SELECT * FROM user;返回:
100条。
事务B:
新增:
1条用户。
事务A:
再次查询:
101条。
多出来的数据像“幻觉”。
十一、MySQL默认隔离级别
InnoDB:
默认:
REPEATABLE READ原因:
性能和一致性的平衡。
十二、事务在后端中的应用
例如 NestJS + TypeORM:
创建订单:
await queryRunner.startTransaction(); try { await createOrder(); await updateStock(); await updateMoney(); await queryRunner.commitTransaction(); } catch(e){ await queryRunner.rollbackTransaction(); }对应:
数据库:
BEGIN SQL1 SQL2 SQL3 COMMIT十三、本节总结
| 概念 | 含义 |
|---|---|
| 事务 | 一组不可分割操作 |
| COMMIT | 提交事务 |
| ROLLBACK | 回滚事务 |
| ACID | 事务四大特性 |
| 原子性 | 全部成功或全部失败 |
| 一致性 | 数据保持正确 |
| 隔离性 | 事务互不影响 |
| 持久性 | 提交后永久保存 |
🎯 本节核心一句话:
事务保证多个数据库操作成为一个不可分割的整体,避免业务执行到一半导致数据错误。