MySQL--REPEATABLE-READ隔离级别下读取到的“重复数据”
在MySQL中,使用MVCC来实现REPEATABLE-READ隔离级别,由于SELECT操作不会对数据加锁,其他回话可以修改当前回话所读取过的数据而不会被阻塞,因此读写不冲突。
在MVCC并发控制中,读操作可以分成两类:快照读 (snapshot read)与当前读 (current read)。快照读,读取的是记录的可见版本 (有可能是历史版本),不用加锁。当前读,读取的是记录的最新版本,并且,当前读返回的记录,都会加上锁,保证其他事务不会再并发修改这条记录。(抄自MySQL 加锁处理分析)
当事务中进行查询时,MySQL会把快照读和当前读的结果进行合并再返回给客户端,而这个合并可能导致一些奇特的结果。
生成测试数据:
drop table tb002; create table tb002(id int primary key,c2 int,unique index uni_c2(c2)); begin; insert into tb002(id,c2) select 1,1; insert into tb002(id,c2) select 2,2; insert into tb002(id,c2) select 4,4; commit;
假设有回话A和回话B,均使用REPEATABLE-READ隔离级别
##========================================================##
首先回话A执行SQL:
begin; select * from tb002;
返回结果如下:
##========================================================##
然后回话B执行SQL:
begin; delete from tb002 where id=2; commit;
由于回话A没有加锁,所以回话B能顺利完成删除并提交事务,当前数据库中无C2=2的记录,且会话B提交事务释放锁。
##========================================================##
回到回话A执行SQL:
insert into tb002(id,c2) select 3,2;
由于当前数据库中无C2=2的记录,且其他回话没有在此C2=2的范围上加锁,因此回话A可以完成C2=2的数据插入。
在回话A上再次进行查询:
select * from tb002;
返回结果如:
C2上有唯一索引,但为什么查询结果中仍包含两条C2=2的记录呢?ID=2的记录属于快照读的数据,ID=3的记录数据当前读的数据,MySQL将当前读和快照读的数据进行简单的合并后返回给客户端,并不检查“结果数据是否满足唯一索引”的要求。
##========================================================##
上面的测试针对唯一索引进行,那如果针对主键会有啥区别呢?
将插入SQL修改为:
insert into tb002(id,c2) select 2,3;
即回话B删除的ID值和回话A新插入的ID值相同情况下,最后的查询结果并不会包含两条相同ID的记录,对于“快照读”和“当前读”两个结果集存在"主键冲突“的情况,最终返回客户端的结果会”丢弃“快照读中的”老版本“记录,保留最新版本的记录。
可见对于主键不存在上述问题。
##========================================================##
总结:
在基于MVCC实现的REPEATABLE-READ隔离级别下,由于快照读和当前读的影响,会导致返回数据结果集超过”期望结果集“的情况,甚至返回结果集中包含重复的”唯一索引键“,但返回结果集中不会包含重复的“主键”(PS:单表查询的前提下)。
如果在事务中包含先插入后查询的情况,应该考虑上述问题对业务的影响。
##========================================================##
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现