浅谈MySQL:事务的ACID和隔离级别

事务的ACID

说到MySQL事务的ACID,大家应该都不陌生,有很多人认为必须完全满足ACID才是一个合格的事务,但实际上并不是这样,真正能满足ACID的事务少之又少。可以说ACID并不是事务必须满足的条件,而是用来衡量事务的四个不同维度。

Atomic 原子性

一个事务的所有操作步骤被看成是一个动作,所有的步骤要么全部完成要么一个也不会完成。如果事务过程中任何一点失败,将要被改变的数据库记录就不会被真正被改变,而是回到事务执行之前的状态,也就是事务回滚。

Consistent 一致性

根据定义,一致性是指事务执行前后,数据处于一种合法的状态,这种状态是语义上的而不是语法上的。
那什么是合法的数据状态呢?这个状态是满足预定的约束就叫做合法的状态,再通俗一点,这状态是由你自己来定义的。满足这个状态,数据就是一致的,不满足这个状态,数据就是不一致的。
其实一致性的实现依靠的就是其他3个特性,也可以说一致性是事务的最终目的。

Isolated 隔离性

隔离性研究的是不同事务之间的相互影响,主要用于实现并发控制,隔离能够确保并发执行的事务能够顺序一个接一个执行,通过隔离,一个未完成事务不会影响另外一个未完成事务。
关于隔离性的探讨,主要可以分为两个方面:

  • 一个事务写操作对另一个事务写操作的影响:锁机制保证隔离性
  • 一个事务写操作对另一个事务读操作的影响:MVCC保证隔离性

Durable 持久性

一旦一个事务被提交,它应该持久保存,不会因为和其他操作冲突而取消这个事务。很多人认为这意味着事务是持久在磁盘上,但是规范没有特别定义这点。

事务的隔离级别

下面来聊一下事务的几种隔离级别。

Read Uncommitted 读未提交

就是说某个事务还没提交的时候,修改的数据,就让别的事务给读到了,如果这个事务回滚了,就很容易出错。
该隔离级别很少使用到,也被称为脏读

Read Committed 读已提交

一个事务开始时,只能“看见”已经提交的事物所做的修改。换句话说一个事务从开始直到提交之前,所做的任何修改都是对其他事务不可见的。
大多数的数据库默认的隔离级别是读已提交,但是Mysql不是。这个级别也叫作不可重复读

Read Repeatable 可重复读

该级别保证了在同一个事务多次读取同样记录的结果是一致的,哪怕这条记录被其他事务修改并提交了,解决了脏读了问题。
但是可重复读还是无法解决幻读的问题,幻读就是指的是当某个事务在读取某个范围内的记录的时候,另外一个事务又在该范围内插入了新的记录,当之前的事务再次读取该范围的记录时候就会产生幻行。
可重复读是Mysql的事务的默认隔离级别,InnoDB和XtraDB存储引擎通过版本并发控制解决而了幻读的问题。

Serializable 串行化

是最高的隔离级别,通过强制事务串行化执行,避免了前面所说到的幻读的问题。设置该隔离级别,会在读取的每一行数据上都加上锁,但是这样会导致超时和锁争用问题,实际生产环境也很少使用。

总结一下几种隔离级别存在的问题:

事务隔离级别 脏读 不可重复读 幻读
Read Uncommitted 读未提交
Read Committed 读已提交 ×
Read Repeatable 可重复读 × ×
Serializable 串行化 × × ×
posted @ 2021-11-27 16:08  远古时代的程序猿  阅读(60)  评论(0编辑  收藏  举报