详解MySQL隔离级别

2022-08-25 00:00:00 数据 事务 提交 隔离 复读

一个事务具有ACID特性,也就是(Atomicity、Consistency、Isolation、Durability,即原子性一致性隔离性持久性),本文主要讲解一下其中的Isolation,也就是事务的隔离性

概述

四种隔离级别分别是:

  • 读未提交(read uncommitted)
    • 一个事务还没提交时,它修改的数据都可以被别的事物看到。
  • 读已提交(read committed)
    • 一个事务提交之后,它修改的数据才会被别的事物看到。
  • 可重复读(repeatable read)
    • 一个事务执行过程中看到的数据,总是和这个事务开启时看到的数据是一致的。在可重复读的隔离级别下,未提交的事务对其他事务也是不可见的。
  • 串行化(serializable)
    • 数据的都会加锁会加读锁会加写锁。当遇到读写锁冲突时,后访问的事务必须等前一个事务执行完成后,再继续执行。

以上四种隔离级别,由上往下隔离强度越来越大,但是执行效率会随之降低。在设置隔离级别时候,需要在隔离级别执行效率两者做平衡取舍。

为了便于理解,下面就举一个例子:


在不同隔离级别下,事务A会有哪些不同的返回结果,也就是图中的V1V2V3的返回值分别是什么。

  • 如果隔离级别是读未提交,事务B修改后数据无需提交事务,就能被事务A读取,所以V1V2V3的值都是2
  • 如果隔离级别是读已提交,事务B修改后需要提交后,修改后的数据才能被事务A读取,所以V1的值是1事务B提交,事务A读取修改后的数据,所以V2的值是2,V3的值也是2
  • 如果隔离级别是可重复读,整个事务看到的事务和事务开启时看到的数据是一致的,开启看到的数据是1,所以V1V2的值都是1,事务A提交之后,获取到修改后的数据,所以V3的值是2
  • 如果隔离级别是串行化,会被锁住,此时事务B对应的线程处于阻塞状态,直到事务A提交之后,事务B才会继续将1改成2。所以V1V2的值是1V3的值是2

MySQL默认的隔离级别是可重复读

隔离级问题

先了解几个基本概念:

脏读事务A修改数据,事务B读取了数据后事务A报错回滚,修改的数据没有提交到数据库中,此时事务B读取修改的数据就是一个脏读,也就是一个事务读取到另一个事务未提交的数据就是脏读

不可重复读事务A在同一个事务上多次读取同一个数据,在事务A还没有结束时,事务B修改了该数据,由于事务B的修改,导致事务A两次读取的数据不一致,就出现了不可以重复读的现象。

幻读事务A根据条件查询得到N条数据,但此时事务B更改或者增加了M条符合事务A查询的条件的数据。这样当事务A再次查询的时候发现会有N + M条数据,产生了幻读。

几种隔离级别可能会有脏读不可重复读或者幻读的问题,它们之间的关系如下:

隔离级别脏读不可重复读幻读
读未提交
读提交×
可重复读××
串行化×××

相关文章