目录
脏读:读到了其他事务未提交的数据,脏数据,无效数据。
不可重复读:读到了其他事务已提交的数据(update),指同一个事务内的多次相同的查询却返回了不同数据。
幻读:读到其他事务已提交的数据(delete,insert),指同一个事务内多次查询返回的结果集不一样
要想解决脏读、不可重复读、幻读等读现象,那么就需要提高事务的隔离级别。但是随之带来的,隔离级别越高,并发能力越低。所以,需要根据业务去进行衡量,具体场景应该使用哪种隔离级别
1.事务的特性(ACID)
(1)原子性(Atomicity)
事务是一个不可分割的工作单位,事务中的操作要么都成功,要么都失败。
(2)一致性(Consistency)
事务前后数据的完整性必须保持一致,事务执行前和执行后来源和去向保持平衡。
(3)隔离性(Isolation)
事务之间互不干扰,多个用户并发操作数据库时,一个用户的事务不能被其它用户的事务所干扰,多个并发事务之间数据要相互隔离。
(4)持久性(Durubility)
一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响。
2.事务隔离级别(SQL 标准定义了四个隔离级别)
(1)read uncommitted 未提交读
所有事务都可以看到没有提交事务的数据。
最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读。
(2)read committed 提交读 (oracle默认事务级别)
事务成功提交后才可以被查询到。
(3)repeatable read 重复读 (mysql默认事务级别)
同一个事务多个实例读取数据时,可能将未提交的记录查询出来,而出现幻读。
不允许其他事务update,但允许其他事务insert或delete导致幻读
(4)Serializable可串行化
数据库事务的最高隔离级别。在此级别下,事务串行执行。可以避免脏读、不可重复读、幻读等读现象。但是效率低下,耗费数据库性能,不推荐使用。
强制的进行排序,在每个读读数据行上添加共享锁。会导致大量超时现象和锁竞争。
级别 | 隔离级别 | 名字 | 说明 |
---|---|---|---|
1 | read uncommitted | 读未提交 | 允许读取尚未提交的数据 |
2 | read committed | 读已提交 | 允许读取并发事务已经提交的数据 |
3 | repeatable read | 可重复读 | 对同一字段的多次读取结果都是一致的, 除非数据是被本身事务自己所修改,查询期间,不允许其他事务update |
4 | serializable | 串行化 | 所有的事务依次逐个执行, 这样事务之间就完全不可能产生干扰,查询期间,不允许其他事务insert或delete |
隔离级别 | 名字 | 脏读 | 不可重复读 | 幻象 | 说明 |
---|---|---|---|---|---|
read uncommitted | 读未提交 | 是 | 是 | 是 | 如果其他事务更新,不管是否提交,立即执行 |
read committed | 读已提交 | 否 | 是 | 是 | 读取提交过的数据。如果其他事务更新没提交,则等待 |
repeatable read | 可重复读 | 否 | 否 | 是 | 查询期间,不允许其他事务update |
serializable | 串行化 | 否 | 否 | 否 | 查询期间,不允许其他事务insert或delete |
3.查询当前事务隔离级别 mysql
-- Mysql8 以前
SELECT @@GLOBAL.tx_isolation, @@tx_isolation;
-- Mysql8
SELECT @@GLOBAL.transaction_isolation, @@transaction_isolation;
4.设置事务隔离级别 mysql
set session transaction isolation level 隔离级别;
eg: 设置事务隔离级别为:read uncommitted,read committed,repeatable read,serializable
set session transaction isolation level read uncommitted;
5.其他
- 事务隔离机制的实现基于锁机制和并发调度。其中并发调度使用的是MVVC(多版本并发控制),通过保存修改的旧版本信息来支持并发一致性读和回滚等特性。
- 因为隔离级别越低,事务请求的锁越少,所以大部分数据库系统的隔离级别都是read committed(读已提交),但是InnoDB 存储引擎默认使用 repeatable read(可重读)且不会有任何性能损失。
- InnoDB 存储引擎在 分布式事务 的情况下一般会用到serializable(可串行化)隔离级别。