浅谈MySQL的四种隔离级别

21-07-13 18:02 字数 1344 阅读 1024 已编辑

众所周知,MySQL的四种隔离级别分别是

  1. READ UNCOMMITTED (读未提交)
  2. READ COMMITTED (读已提交)
  3. REPEATABLE READ (可重复读)
  4. SERIALIZABLE (串行化)

从上到下,隔离的级别越来越高,但性能越来越差。MySQL为什么要有隔离性呢?就要引出实际业务中可能出现的问题。

脏读

简单理解就是当前同时存在2个及以上的事务,即并发环境下,事务1读取到了事务2中未提交的数据,比如事务2修改userage字段从1改为25,在事务2还未提交时,这条数据就被事务1读到了。

有什么问题?

假如事务2修改age25后,因为某些原因回滚了事务,那么事务1读到的25就是“脏数据”,比如事务1继续拿这个“脏数据”做了一些操作,那么后续的操作都是不合理的。.

READ UNCOMMITTED (读未提交) 无法解决脏读的问题

不可重复读

这就引出了 READ COMMITTED (读已提交),read commited 顾名思义就是在一个事务中(只)能读到另一个事务已提交的数据。还是上面的例子,同时存在两个事务,事务1中将age字段从1改为25,在事务1没有提交之前,事务2中查询到的age都是1。直到事务1提交了,事务2再次读取的age才是25;如此一来就解决了“脏读” 的问题,但是这样就完美了吗?

有什么问题?

仔细考虑我们发现,事务2在一个事务周期的不同时刻,读取的age字段是不一样的。在事务1未提交前,读取到的是1,事务1提交后,读取的到的是25。这就是不可重复读。

READ COMMITTED (读已提交) 无法解决不可重复读的问题

幻读

为了解决不可重复读的问题,自然引出 REPEATABLE READ (可重复读),repeatable read 是什么意思呢,意思就是上面的例子中,事务2,从始至终读取的age都是1,不管事务1有没有提交。

有什么问题?

可重复读解决了不可重复读的问题,但是假如有下面的场景。

同时存在两个事务,事务1查询了user表中age=25的数据,现在表里只有一条符合条件数据,自然查出了一条数据,假如现在事务2插入一条age=25的数据,之后事务1又查询了一下age=25的记录,此时发现竟然查出了两条记录,刚才明明还是一条,怎么现在出现了两条。即:本次查询出现了上次查询未出现的记录,像幻觉一样,这就是所谓幻读

注意

REPEATABLE READ (可重复读) 通过 MVCC(多版本并发控制)GAP LOCK(间隙锁) 的机制已经解决了幻读的问题。

SERIALIZABLE (串行化) 是4种事务隔离级别中隔离效果最好的,解决了脏读、可重复读、幻读的问题,但是性能最差,它将事务的执行变为顺序执行,与其他三个隔离级别相比,它就相当于单线程,后一个事务的执行必须等待前一个事务结束。

参考

https://baijiahao.baidu.com/s?id=1662096005584873447&wfr=spider&for=pc https://blog.csdn.net/hanpeiyu1995/article/details/90201894

0人点赞>
关注 收藏 改进 举报
0 条评论
排序方式 时间 投票
快来抢占一楼吧
请登录后发表评论
站长 @ 十七度
文章
384
粉丝
23
喜欢
195
收藏
31
排名 : 1
访问 : 147.28万
私信