Mysql事务隔离级别对比

隔离级别内容

事务隔离级别内容如下:

隔离级别 脏读(Dirty Read) 不可重复读(NonRepeatable Read) 幻读(Phantom Read)
未提交读(Read uncommitted) 可能 可能 可能
已提交读(Read committed) 不可能 可能 可能
可重复读(Repeatable read)(InnoDB默认) 不可能 不可能 可能
可串行化(Serializable ) 不可能 不可能 不可能

事务隔离级别是为了解决事务并发的时候产生的问题。具体来说会产生3类问题:脏读、不可重复读、幻读。还有一个特例就是丢失更新,这个问题在已提交读和未提交读这两个级别上存在。

3类问题

脏读

一个事务读取到了另一个事务未提交的数据。

时间 事务A 事务B
T1 开启事务 开启事务
T2 查询余额100 查询余额100
T3 修改余额为110
T4 查询余额110
T5 rollback

在上面的时序图中在事务A在T4时间点读取到的余额就是错的,因为事务B在T5时刻会将之回滚。

不可重复读

当隔离级别是已提交读(Read commited)的时候,一个事务只能读取另一个事务已经提交的数据,这就会出现不可重复读的问题。

时间 事务A 事务B
T1 开启事务 开启事务
T2 查询余额100 查询余额100
T3 修改余额为110
T4 查询余额100
T5 commit
T6 查询余额110
T7 commit

事务A在T6时刻发生了不可重复读,因为在同一事务内查询统一纪录,其结果不一致。
那么脏读和不可重复读的区别是什么?最大的区别是脏读的数据是错误的(因为rollback),而不可重复读的数据没有错误,只是读取到其他事务已提交的内容而已。

幻读

当事务隔离级别为可重复读(Repeatable read)时,实际上是解决了不可冲重复读的问题。这样在一次事务中,对一个记录查询多次,结果都会相同。也就是说事务和事务之间独立了。这样就会造成另外的问题,幻读。第一个事务对一个表中的数据进行了修改,这种修改涉及到表中的全部数据行。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么,以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行,就好象发生了幻觉一样。

时间 事务A 事务B
T1 开启事务 开启事务
T2 select * from table where id=1(结果0条)
T3 insert into table (id) value(1)
T4 commint
T5 select * from table where id=1(结果0条)
T6 insert into table (id) value(1)
T7 commit(主键冲突)

幻读和不可重复读类似,即两次读取的结果不一致,两者的不同点在于,不可重复读针对数据的修改造成的读不一致,而幻读针对数据的插入和删除造成的读不一致。

原文地址:https://www.jdkdownload.com/mysql_isolation.html