前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >MySQL如何解决幻读问题

MySQL如何解决幻读问题

作者头像
AsiaYe
发布2020-06-15 12:29:45
1.4K0
发布2020-06-15 12:29:45
举报
文章被收录于专栏:DBA随笔DBA随笔

//MySQL如何解决幻读问题?//

先来说说幻读的概念吧,在MySQL中,如果一个事务A根据某种特定条件的SQL查询出来一些记录record_a,此时另外一个事务插入了一些符合这种特定条件的记录record_b,原先的事务再次根据同样的SQL,查询到了record_a和record_b,这种现象就称之为幻读。

注意,下面两种情况不能称之为幻读:

1、如果查出来数据比record_a的记录要少,

2、或者查出来的数据跟record_a记录一样,但是记录发生了变化。

幻读强调的是一个事务按照相同的SQL查询了记录之后,后续的结果中出现了之前结果中不存在的值。

在默认RR隔离级别下,当发生了幻读现象之后,MySQL解决这种情况会使用两种方案。

方案一:读操作利用MVCC解决,写操作利用加锁解决

MVCC知识可以查看之前的文章:

《MySQL之MVCC初探(1)

MVCC其实是借助于Readview(读视图)的概念,对数据库生成Readview时刻的版本做了一个快照。普通的查询语句只能看到生成Readview之前已经提交的事务,在生成Readview之前未提交的事务或者生成Readview之后才开启的事务是看不到的。MVCC情况下读取的都是记录的历史版本,而写操作都是更新的是记录的最新版本,因此,MVCC情况下,读操作和写操作本身并不冲突。

说的更简单一点就是RR隔离级别下,事务在第一次select的时候只生成一次Readview(类似拍了一张照片),后续的查询都复用这个Readview(同样的照片),当然,也就不会出现幻读现象了。

方案二:读写操作都采用加锁的方式

在银行支付等场景下,不允许读取记录的历史版本,只允许看到记录的最新版本,此时读操作和写操作都需要加锁,其实,要解决幻读问题,只添加记录锁于事无补,因为幻读的记录在第一次读取之前是不存在的,即使你给记录上了记录锁,但是不存在的记录上面如果没有锁,还是会造成幻读。

为了解决这个问题,MySQL引入了间隙锁,间隙锁的引入,阻止了其他会话在指定的间隙插入相关记录,也就解决了幻读的问题。

两种方案对比:

如果采用MVCC方式的话,只能解决一致性非锁定读(也称之为快照读)的幻读问题,读-写操作彼此并不冲突,并发性能更高;

如果采用加锁方式的话,可以解决当前读的幻读情况,读-写操作彼此需要排队执行,影响性能;

一般情况下我们当然愿意采用MVCC来解决读-写操作并发执行的问题,但在银行业务等特殊场景下,还是需要锁来解决的。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-06-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 DBA随笔 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
云数据库 SQL Server
腾讯云数据库 SQL Server (TencentDB for SQL Server)是业界最常用的商用数据库之一,对基于 Windows 架构的应用程序具有完美的支持。TencentDB for SQL Server 拥有微软正版授权,可持续为用户提供最新的功能,避免未授权使用软件的风险。具有即开即用、稳定可靠、安全运行、弹性扩缩等特点。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档