面试必知:MySQL事务、隔离级别、脏读、不可重复读、幻读
无论你是后端还是DBA,这是一道几乎必考的题目。
MySQL的事务具有哪些特性?
原子性:一个事务中的sql,要么都成功,要么都失败。
一致性:假如事务a更新 m和n两个数据源,那么对于其它事务来说,无论事务a成功或者失败,其它事务读到的m和n的状态,要么都是更新前的,要么都是更新后的。
隔离性:事务a执行过程中,对数据的更改,对其它事务来说是隔离的,至于是否可见,是由事务的隔离级别控制的。
持久性:事务对数据的更改是持久落地的。不会凭空消失。
事务的隔离级别有哪些?
事务在不同的隔离级别下,特性是不一样的,一般最起码要保证原子性,一致性和持久性。所以MySQL默认隔离级别一般是可重复读。
1.读未提交 2.读已提交 3.可重复读 4.串行化
什么是脏读?
脏读简单来讲就是读到另一个事务的相对错误数据,只有在读未提交隔离级别下才会出现这种情况。
假如事务A在读未提交隔离级别下读取到一条事务B正在修改的数据,然后由于某种原因,事务B失败了,但是事务A正常执行了,这种情况下,事务A最终读取到的是错误的数据,这就是脏读。
什么是不可重复读?
事务执行过程中,前后读取得数据不一致,这就是不可重复读。在<读未提交>隔离级别下,事务开始读到一个数据,然后另一个事务修改了数据,无论另一个事务提交与否,前一个事务再读这一条数据的时候都会读到不一样的值。
在<读提交>隔离级别下,同样会遇到这样的问题,事务A开始读到一个数据,另一个事务修改了这个数据,并且commit,这时候事务A再读这条数据就会读到不一样的值。
什么是幻读?
幻读在实际开发过程中,即使碰到后只会影响瞬时插入,不会影响数据的正确性。幻读的危害远远小于脏读和不可重复读。
假设有两个事务A和B,当事务A正要插入一条不数据时,查询ID为1的数据不存在,恰好这时事务B已经成功插入了同一个唯一ID为1的数据,这时事务A执行插入就会因为主键冲突报错,但是在事务A中执行查询ID为1的数据缺不存在,这就是幻读。幻读只有在<串行化>隔离级别下才不会出现,其他隔离级别都会出现。但是如果为了避免幻读,而将隔离级别设置为串行化,那么数据库的并发性能将会骤降,一般不会这么做。
总结:
事务的隔离级别越高,事务的特性越能得到保证,但是数据库的并发性能会越低。相反同理。
MySQL 默认的隔离级别是可重复读,这种隔离级别下,不会出现脏读和不可重复读的状况,只会出现幻读。所以在保证事务原子和隔离特性的情况下,又想提高数据库性能和并发能力,一般设置事务的隔离级别为可重复读。