事务的概念
简单来说,事务就是保证一组数据库操作,要么全部成功,要么全部失败。在MySql是一个支持多引擎的系统,但并不是所有的引擎都支持事务。比如MySql原生的MyISAM引擎就不支持事务,这也是MyISAM被InnoDB取代的重要原因之一。
事务的特性
事务的特性分为ACID(Atomicity.Consistency、lsolation、Durability )即原子性,一致性,隔离性,持久性
- 原子性:是指事物的原子性,对数据库数据的一系列操作要么全部成功,要么全部失败。基于Redo/Undo机制
- 一致性:是指执行事务前后的状态要一致,指数据一致
- 隔离性:隔离性是指多个事务之间的操作相互隔离,不受影响,这个与数据库设置的隔离级别有关。
- 持久性:持久性是指一个事务提交以后,这个事务的状态会被持久到数据库中,也就是事务提交以后,对数据的新增丶更新会永久的存储到磁盘中。
Redo/Undo机制
Redo log记录的是某数据被修改后的值,可以用来恢复tada file的已经成功提交事务的数据,Undo log是记录数据更新前的值,保证数据更新失败时候进行回滚
假如在数据库执行事务的过程中,突然崩溃,可以通过日志的方式,回滚到已经成功执行的操作,实现事务的一致性。
举例说明
现在有俩个事务,一个事务A,一个事务B,在操作数据库,这时事务A已经成功提交,事务B还未提交,数据库突然发生崩溃。这时,数据库在重启进行crash-recovery (崩溃恢复)时,会通过Redo log 将已经成功提交的事务的操作更新到数据文件,还未提交的通过Undo log 进行回滚。
事务的隔离级别
当数据库上有多个事务同时执行的时候,就可能出现脏读(dirty read)、不可重复读(non-repeatable read)、幻读(phantom read)的问题,为了解决这些问题,就有了“隔离级别”的概念。
MySQL默认的隔离级别是可重复读
- 读取未提交:一个事务还没有提交,但是对数据的变更可以被其他事务看到。
- 读取已提交:一个事务提交之后,他做的变更才可以被其他数据看到。
- 可重复读:一个事务在提交之前,在执行过程中看到的数据是一致的。
- 串行化:会对同一行记录加锁,当出现对同行数据的读写冲突的时候,必须等待前一个事务执行完,后一个事务才可以执行。
举例
我们来看看在不同的隔离级别下,事务A会有哪些不同的返回结果,也就是图里面V1、V2.V3的返回值分别是什么。
-
若隔离级别是“读未提交”,则V1的值就是2。这时候事务B虽然还没有提交,但是结果已经被A看到了。因此,V2、V3也都是2。
-
若隔离级别是“读提交”,则V1是1,V2的值是2。事务B的更新在提交后才能被A看到。所以,V3的值也是2。
-
若隔离级别是“可重复读”,则V1、V2是1,V3是2。之所以V2还是1,遵循的就是这个要求:事务在执行期间看到的数据前后必须是一致的。
-
若隔离级别是“串行化”,则在事务B执行“将1改成2”的时候,会被锁住。直到事务A提交后,事务B才可以继续执行。所以从A的角度看,V1、V2值是1,V3的值是2。
脏读,不可重复读,幻读
- 脏读:
当数据库中一个事务A正在修改一个数据但是还未提交或者回滚,
另一个事务B 来读取了修改后的内容并且使用了,
之后事务A提交了,此时就引起了脏读。
此情况仅会发生在: 读未提交的的隔离级别.
- 不可重复读:
在一个事务A中多次操作数据,在事务操作过程中(未最终提交),
事务B也才做了处理,并且该值发生了改变,这时候就会导致A在事务操作
的时候,发现数据与第一次不一样了。 就是不可重复读。
此情况仅会发生在:读未提交、读提交的隔离级别.
- 幻读:
一个事务按相同的查询条件重新读取以前检索过的数据,
却发现其他事务插入了满足其查询条件的新数据,这种现象就称为幻读。
幻读是指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,比如这种修改涉及到表中的“全部数据行”。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入“一行新数据”。那么,以后就会发生操作第一个事务的用户发现表中还存在没有修改的数据行,就好象发生了幻觉一样.
一般解决幻读的方法是增加范围锁RangeS,锁定检索范围为只读,这样就避免了幻读。
此情况会回发生在:读未提交、读提交、可重复读的隔离级别.