MySQL事务
1. 🎯什么是事务?
事务(Transaction)是指一个或者多个SQL语句的整合,这个组合要么都执行要么都不执行。
2. 🎯MySQL事务的四大特性
原子性
(Atomicity):事务中的SQL语句要么都执行要么都不执行。一致性
(Consistency):数据库由一种有效状态转换为另一种有效状态。例如转账操作事务,事务结束后转收方的总额是不变的。
持久性
(Durability):事务一旦执行完毕,那么是确实对数据库的修改,是一直保存在数据库中的。隔离性
(Isolation):并发
执行的事务不会相互影响。
3. 🎯并发执行的事务为什么要保证不相互影响,怎么保证的?
-
并发执行的事务会导致以下
读一致性
问题-
脏读:如果一个事务读取到了另一个未提交事务修改过的数据,这个数据不是最终数据,那么我们就称发生了脏读现象。
人家修改着你读了
。 -
不可重复读:一个事务内的多次读操作的结果是不一样的。
人家读着你修改或者删除了
。 -
幻读:一个事务内的多次读操作的结果是不一样的,这个结果是指结果数量变多了。
人家读着你增加或者修改了
。
-
-
对应问题的解决方案和隔离级别
问题 解决的方案 脏读 当一个事务修改数据时不让其他事务读( ReadView + MVCC
)不可重复读 当一个事务读数据时不让其他事务修改或者删除( ReadView + MVCC
)幻读 串行执行事务,当一个事务读数据时不让其他事务添加或者修改( 读锁 + 写锁
)SQL92标准中对“不可重复读”和“幻读”的描述
不可重复读:事务T1读取了一条记录
,事务T2修改或者删除了同一条记录,并且提交。如果事务T1试图再次读取同一条记录的时候,会读到被事务T2修改的数据或者压根读不到。
幻读:事务T1首先读取了符合某些搜索条件P的一些记录
。然后事务T2执行了某些SQL语句产生了符合搜索条件P的一条或多条记录。如果事务T1再次读取符合条件P的记录,将会得到不同于之前的数据集
区别:
1.操作步骤
a. 不可重复读是由于其他事务的修改或者删除
b. 幻读是由于其他事务的修改或者插入
2.操作对象
a. 不可重复读是针对一条记录
b. 幻读是针对一些记录
读已提交和可重复读的实现方法区别
都是通过MVCC的方式实现的,具体的区别在于ReadView
READ COMMITTED
隔离级别:每次select都生成一个快照读。
REPEATABLE READ
隔离级别:开启事务后第一个select语句生成快照读,后续的快照读获取的都是同一个。
-
隔离级别
解决的问题 隔离级别 无 Read Uncommitted(读未提交) 脏读 Read Committed(读已提交) 脏读、不可重复读 Repeatable Read(可重复读) 脏读、不可重复读、幻读 Serializable(串行化) 隔离级别高的具备隔离级别低的功能
自上而下隔离级别逐步升高,但是效率逐步下降。
MySQL 在「可重复读」隔离级别下,可以很大程度上避免幻读现象的发生(注意是很大程度避免,并不是彻底避免),所以 MySQL并不会使用「串行化」隔离级别来避免幻读现象的发生,因为使用「串行化」隔离级别会影响性能。
-
MySQL InnoDB 引擎的
默认隔离级别
虽然是「可重复读」,但是它很大程度上避免幻读现象(并不是完全解决了),解决的方案有两种: -
针对快照读(普通 select 语句),是通过 多版本并发控制(MVCC )方式解决了幻读,因为可重复读隔离级别下,事务执行过程中看到的数据,一直跟这个事务启动时看到的数据是一致的,即使中途有其他事务插入了一条数据,是查询不出来这条数据的,所以就很好了避免幻读问题。
-
针对当前读(select … for update 等语句),是通过
next-key lock(记录锁+间隙锁)
方式解决了幻读,因为当执行 select … for update 语句的时候,会加上 next-key lock,如果有其他事务在 next-key lock 锁范围内插入了一条记录,那么这个插入语句就会被阻塞,无法成功插入,所以就很好了避免幻读问题。