MySQL5️⃣事务(❗)
事务(Transaction)
-
一组操作的集合,不可分割的工作单位。
-
把所有操作视为一个整体,向系统提交或撤销请求。
-
MySQL 默认自动提交
(👉 每执行一条 DML 语句,MySQL 立即将事务提交到数据库)
1、操作
-
控制事务:两种方式
-
关闭自动提交:
# 查看 SELECT @@autocommit; # 0-关闭,1-开启 SET @@autocommit = 0;
-
手动开启事务:
# 写法一 START TRANSACTION; # 写法二 BEGIN;
-
-
提交事务:事务正常时执行。
COMMIT;
-
回滚事务:事务异常时执行。
ROLLBACK;
2、特性
2.1、ACID
含义 | 理解 | |
---|---|---|
原子性 (Atomicity) |
事务是不可分割的最小操作单元 | 要么都成功,要么都失败 |
一致性 (Consistency) |
事务完成时,必须使所有数据保持一致状态 | 要么都提交,要么都不提交 |
隔离性 (Isolation) |
保证事务在独立环境下运行,不受外部并发操作影响 | 事务 A 不影响事务 B |
持久性 (Durability) |
事务一旦提交或回滚,结果就被持久化到存储器中 |
2.2、说明
一致性 vs 隔离性
- 一致性:单个事务前后的数据保持一致。
- 隔离性:多个事务之间不会互相影响。
3、并发 & 隔离
3.1、并发事务问题
场景:多个事务并发读写数据库。
含义 | 理解(事务 A, B) | 结果 | |
---|---|---|---|
脏读 | 读到另一个事务未提交的数据 | A 读到一条记录,此时 B 更新了该记录但未提交 | A 读到的不是最新数据 |
不可重复读 | 先后读取同一条记录,但两次读取的数据不同 | A 先后读同一条记录,在此期间 B 修改了记录 | A 两次读取的结果不同 |
幻读 | 查询不到某条记录,试图插入记录时却提示已存在 | A 查 id = 7 时发现不存在,准备插入 id = 7 的记录。但在此期间 B 插入了 id = 7 的记录 | A 查不到也插不了 |
3.2、隔离级别
3.2.1、类型
-
关系:与数据安全性成正比,与性能成反比。
-
解决问题:见下表 ✔
含义 脏读 不可重复读 幻读 RU Read uncommitted(读未提交) - - - RC Read committed(读已提交) ✔ - - RR Repeatable Read(可重复读)
MySQL 默认✔ ✔ - Serializable 序列化 ✔ ✔ ✔
3.2.2、使用
-
查看:
SELECT @@TRANSACTION_ISOLATION;
-
设置:
-
SESSION:当前会话生效。
-
GLOBAL:全局生效。
SET [SESSION|GLOBAL] TRANSACTION ISOLATION LEVEL 类型;
-
Spring:事务传播行为
事务传播行为(propagation behavior)
Spring 框架的事务增强特性。
- 含义:当事务方法调用另一个事务方法时,由被调用者决定如何运行。
- 类型:Spring 在 TransactionDefinition 接口中定义的 7 种类型。
方法 A 调用方法 B 时,B 的可选策略如下。
含义 | A 有事务 | A 无事务 | |
---|---|---|---|
REQUIRED | 必需(默认) | 加入 | 新建事务 |
SUPPORTS | 支持 | 加入 | 非事务运行 |
MANDATORY | 强制 | 加入 | 抛出异常 |
REQUIERS_NEW | 要求新的 | 挂起并新建事务 | 新建事务 |
NOT_SUPPORTED | 不支持 | 挂起 | 非事务运行 |
NEVER | 不使用 | 抛出异常 | 非事务运行 |
NESTED | 嵌套 | 在嵌套事务内运行 | 新建事务 |
补充:NESTED 嵌套事务——在当前事务上开启一个子事务(save point)。
- 主事务提交:子事务也会提交。
- 子事务提交:提交子事务 + 前面一部分主事务。