美文网首页
MySQL InnoDB事务隔离级别

MySQL InnoDB事务隔离级别

作者: 哈密朵 | 来源:发表于2019-07-17 22:17 被阅读0次

    一、读未提交(Read Uncommitted)
    这种事务隔离级别下,select语句不加锁。 此时,可能读取别的事务还未提交的insert数据,即“读脏”。这是并发最高,一致性最差的隔离级别。几乎不采用。

    二、读提交(Read Committed, RC)
    这是互联网最常用的隔离级别。
    普通读是MVCC快照读。 加锁读, update, delete等语句,不会使用gap锁和next-key锁,除了在外键约束检查(foreign-key constraint checking)以及重复键检查(duplicate-key checking)时会封锁区间,其他时刻都只使用记录锁,因此加锁读仍能别的事务中途insert提交的记录,完全不能解决幻读。另外MVCC是每次都建立新快照,所以事务内多次普通读仍可能出现不可重复读。

    三、 可重复读(Repeated Read, RR)
    MySQL的默认隔离级别。
    普通读是MVCC快照读。加锁读, update, delete等语句, 除了在唯一索引上使用指定ID查询时只使用record锁,辅助索引或任意索引的范围查询时都会使用gap锁和next-key锁, 锁住索引记录之间的范围,避免范围间插入记录,解决加锁情况下的幻读。非加锁即MVCC普通读只在初次建立快照,虽然避免了不可重复读,但先普通读再DML时仍可能出现幻读。

    四、 串行化(Serializable)
    所有select语句都会被隐式的转化为select ... in share mode. 这可能导致,如果有未提交的事务正在修改某些行,所有读取这些行的select都会被阻塞住。 这是一致性最好的,但并发性最差的隔离级别。几乎不采用。

    读提交(Read Committed, RC)和可重复读(Repeated Read, RR)的MVCC区别:
    MVCC读取的是常规的行数据,加上回滚段的变更未提交数据的历史快照。
    事务总能够读取到,自己写入(update /insert /delete)的行记录。
    RC下,快照读总是能读到最新的行数据加最新的回滚段快照,当然,必须是已提交事务写入的行数据。
    RR下,事务首次快照读之后,再次快照读不会刷新别的事务新提交写入的记录和最新的回滚段快照,即和并发事务的开始时间先后没关系,和RR事务首次快照读的时间有关。

    微信截图_20190717221313.png

    不可重复读和幻读的区别:
    大致的区别在于不可重复读是由于另一个事务对数据的更改所造成的,而幻读是由于另一个事务插入或删除引起的。
    似乎两者都表现为两次读取的结果不一致,但从控制的角度来看,两者的区别就比较大:
    对于前者,只需要锁住满足条件的记录; 对于后者, 要锁住满足条件及其相近的记录。

    RC的加锁读能解决不可重复读,但RC的MVCC快照读是每次读取最新快照,还是会读到别的事务刚update的内容,会有不可重复读。
    RR的加锁读能解决不可重复读,RR的MVCC快照读是第一次快照,不理会别的事务刚提交的update,也避免了不可重复读。
    RR的加锁读会加上gap间隙锁,禁止别的事务在相邻范围insert,解决了部分幻读。但RR的快照读不会加上gap间隙锁,而且因为一次性快照的原因不理会别的事务刚提交的insert,等到自己锁读或DML时才发现可能跟别的事务刚提交的insert有冲突,还是有幻读的场景。

    相关文章

      网友评论

          本文标题:MySQL InnoDB事务隔离级别

          本文链接:https://www.haomeiwen.com/subject/tilhlctx.html