3、数据库的事务隔离级别有哪些?【高频】
数据库的事务隔离级别有哪些?
- 缘起:
- 三种并发问题:
- 四种隔离级别:
- 原理:
缘起:
- 多个事务并发执行时,会引发脏读、不可重复读、幻读这些问题,那为了避免这些问题,SQL 提出了四种隔离级别,分别是读未提交、读已提交、可重复读、串行化,从左往右隔离级别顺序递增,隔离级别越高,意味着性能越差(InnoDB 引擎的默认隔离级别是可重复读)
三种并发问题:
- 脏读(因为A提交慢了,所以B脏读A了):如果一个事务读到了 未提交事务 【修改过】的数据,就意味着发生了「脏读」现象。
- 不可重复读(因为B提交快了,所以A不可重复读B):在一个事务内多次读取同一个数据,如果出现前后两次读到的数据不一样的情况,就意味着发生了「不可重复读」现象。
- 幻读(因为A提交快了,所以B幻读A了):在一个事务内多次查询 某个符合查询条件 的记录数量,如果出现 前后两次查询到的 记录数量不一样 的情况,就意味着发生了「幻读」现象。
四种隔离级别:
- 读未提交(Read Uncommitted):
- 指一个事务还没提交时,它做的变更就能被其他事务看到
- 最低的隔离级别,存在脏读、不可重复读和幻读的问题。
- 读提交(Read Committed):
- 一个事务只能读取已经提交的数据,也就是 提交之后,它做的变更才能被其他事务看到
- 解决了脏读问题,但仍可能出现不可重复读和幻读。
- 重复读(Repeatable Read):
- 事务执行期间,多次读取同一数据会得到相同的结果,也就是 一个事务执行过程中看到的数据,一直跟这个事务启动时看到的数据是一致的
- 解决了不可重复读问题,但仍可能出现幻读。
- 串行化(Serializable):
- 会对记录加上读写锁,在 多个事务对这条记录进行 读写操作时,如果发生了 读写冲突 ,后面的事务必须等前一个事务执行完成,才能继续执行
- 最高的隔离级别,不会出现脏读、不可重复读和幻读。
原理:
-
对于「读提交」和「可重复读」隔离级别的事务来说,它们是通过 Read View 来实现的,它们的区别在于创建 Read View 的时机不同:
-
「读提交」是在一个事务中,每次select搜索都会生成一个新的ReadView。事务A在第二次读取一个数据前,如果事务B读取并修改了这个数据并提交它的ReadView,那么这个版本的记录 就可以被事务A获取。从而导致事务A 两次读取的内容不一样,也就是读提交时不能解决重复读问题的
-
「可重复读」是启动事务时生成一个 Read View,然后整个事务期间都在用这个 Read View,所以这个事务 只能读取它启动前版本的记录
-
-
这两个隔离级别实现是通过「事务的 Read View 里的字段(min_trx_id、max_trx_id、m_ids)」和「记录中的隐藏列(trx_id)」的比对,来控制并发事务访问同一个记录时的行为,这就叫 MVCC(多版本并发控制)。
所以,
- 要解决 脏读现象,就要升级到**「读提交」**的隔离级别;
- 要解决 不可重复读现象,就要升级到「**重复读」**的隔离级别,
- 而要解决 幻读现象 不建议将隔离级别升级到「串行化」。因为在「可重复读」隔离级别下,可以很大程度上避免幻读现象的发生(注意是很大程度避免,并不是彻底避免)而且 使用「串行化」隔离级别会影响性能