事务的隔离级别

101 阅读3分钟

参考文章:MySQL事务隔离级别和实现原理(看这一篇文章就够了!)

参考视频:【面试突击】MySQL事务隔离级别(99%的人存在误区)

什么是事务

事务的英文是transaction,而transaction还有交易的意思。事务就是一连串操作( 比如增删改 )的集合。事务内的操作要么全部成功,要么全部失败,如果某一步操作失败,那么这个事务内之前的操作都要回滚。

事务应该具备原子性 (Atomicity)、一致性 (Consistency)、隔离性 (Isolation)、持久性 (Durability)这四个特性,简称acid

acid

  • 原子性:一个事务就是一个完整单元,要么全部成功,要么全部失败。

  • 一致性:事务从开始要结束的任何时刻,数据都是一致的。

  • 隔离性:事务之间是相互独立的,中间状态的数据互不可见。

  • 持久性:数据的修改应该是永久的。

事务的问题

多个事务并发对相同的数据进行操作时,就会出现一系列违反了事务四特性的问题,可总结成以下3个:

  • 脏读

    读到了其他事务未提交的数据,未提交意味着这些数据可能会回滚,也就是可能最终不会存到数据库中,也就是不存在的数据。读到了并一定最终存在的数据,这就是脏读。
    这违背了事务的隔离性。

  • 不可重复读

    在同一事务内,不同的时刻读到的同一批数据可能是不一样的。
    比如:别的事务执行了update操作,并提交了事务。 这违背了事务的一致性。

  • 幻读

    A事务在本次事务中,先读取了一遍数据,发现数据不存在,过了一会,又读取了一遍,发现又有数据了。(破坏了一致性,重点是insert)

事务的隔离级别

为了解决上述的问题,ISO制定了事务隔离级别的标准。

  • 未提交读(read-uncommitted):最低级别,基本只保证持久性;会出现脏读,不可重复读,幻读的问题。
  • 已提交读(read-committed):语句级别;会出现不可重复读,幻读的问题。
  • 可重复读(repeatable-read):事务级别;只会出现幻读问题。
  • 串行化(serializable):最高级别,也就是事务与事务完全串行化执行,无并发可言,性能低;但不会出现任何问题。
事务隔离级别脏读不可重复读幻读
读未提交(read-uncommitted)
不可重复读(read-committed)-
可重复读(repeatable-read)--
串行化(serializable)---

注意:这四个级别只是一个标准,各个数据库厂商,并不完全按照标准做的

实操

查看事务级别

MySQL的Innodb引擎默认的隔离级别:REPEATABLE-READ

# 查看事务隔离级别 5.7.20 之后
show variables like 'transaction_isolation';
SELECT @@transaction_isolation

# 5.7.20 之前
SELECT @@tx_isolation
show variables like 'tx_isolation'

image.png

修改事务隔离级别

set [作用域] transaction isolation level [事务隔离级别]

  • 作用域:session | global
  • 事务隔离级别:READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE

image.png

进行事务操作

begin 命令并不代表事务的开始,事务开始于 begin 命令之后的第一条语句执行的时候。例如下面示例中,select * from xxx 才是事务的开始,

begin;
select * from xxx; 
commit; -- 或者 rollback;