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:单表查询的前提下)。

如果在事务中包含先插入后查询的情况,应该考虑上述问题对业务的影响。

##========================================================##

时间: 2024-11-07 00:00:19

MySQL--REPEATABLE-READ隔离级别下读取到的“重复数据”的相关文章

MySQL Transaction--RR事务隔离级别下加锁测试

============================================================================== 按照非索引列更新 在可重复读的事务隔离级别下,在非索引列上进行更新和删除会对所有数据行进行加锁,阻止其他会话对边进行任何数据的增删改操作. 如果更新或删除条件为c3=4且c3列上没有索引则: 1.不允许其他会话插入任意记录,因为所有记录的主键索引上存在X排他锁,无法申请插入意向X锁(lock_mode X insert intention

MySQL学习总结-演示不同隔离级别下的并发问题

演示不同隔离级别下的并发问题 1.当把事务的隔离级别设置为read uncommitted,会引发脏读.不可重复读和虚读A窗口set transaction isolation level read uncommitted;start transaction;select * from bank;----发现a账户是1000元,转到b窗口select * from bank; B窗口start transaction;update bank set money=money+100 where n

浅谈mysql中不同事务隔离级别下数据的显示效果

事务的概念 事 务是一组原子性的SQL查询语句,也可以被看做一个工作单元.如果数据库引擎能够成功地对数据库应用所有的查询语句,它就会执行所有查询,如果任何一条查 询语句因为崩溃或其他原因而无法执行,那么所有的语句就都不会执行.也就是说,事务内的语句要么全部执行,要么一句也不执行. 事务的特性:acid,也称为事务的四个测试(原子性,一致性,隔离性,持久性) automicity:原子性,事务所引起的数据库操作,要么都完成,要么都不执行consisitency:一致性,事务执行前的总和和事务执行后

mysql中不同事务隔离级别下数据的显示效果--转载

事务是一组原子性的SQL查询语句,也可以被看做一个工作单元.如果数据库引擎能够成功地对数据库应用所有的查询语句,它就会执行所有查询,如果任何一条查询语句因为崩溃或其他原因而无法执行,那么所有的语句就都不会执行.也就是说,事务内的语句要么全部执行,要么一句也不执行. 事务的特性:acid,也称为事务的四个测试(原子性,一致性,隔离性,持久性) automicity:原子性,事务所引起的数据库操作,要么都完成,要么都不执行 consisitency:一致性,事务执行前的总和和事务执行后的总和是不变的

mysql 开发进阶篇系列 12 锁问题(隔离级别下锁的差异)

1. innodb在不同隔离级别下的一致性读及锁的差异 不同的隔离级别下,innodb处理sql 时采用的一致性读策略和需要的锁是不同的,同时,数据恢复和复制机制的特点,也对一些sql的一致性读策略和锁策略有很大影响.对于许多sql, 隔离级别越高,innodb给记录集的锁就越严格(龙其是使用范围条件的时候),产生的锁冲突的可能性也就越高,对并发性事务处理性能的影响也就越大.因此,在应用中,应该尽量使用较低的隔离级别,减少锁争用.通常使用Read Commited隔离级别就足够了, 对于一些确实

[原创]java WEB学习笔记78:Hibernate学习之路---session概述,session缓存(hibernate 一级缓存),数据库的隔离级别,在 MySql 中设置隔离级别,在 Hibernate 中设置隔离级别

本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱好者,互联网技术发烧友 微博:伊直都在0221 QQ:951226918 -----------------------------------------------------------------------------------------------------------------

MySQL基础——事务隔离级别

事务是DBMS得执行单位.它由有限得数据库操作序列组成得.但不是任意得数据库操作序列都能成为事务.一般来说,事务是必须满足4个条件(ACID) ①:原子性(Autmic):事务在执行性,要做到"要么不做,要么全做!",就是说不允许事务部分得执行.即使因为故障而使事务不能完成,在rollback时也要消除对数据库得影响! ②:一致性(Consistency):事务操作之后,数据库所处的状态和业务规则是一致的;比如a,b账户相互转账之后,总金额不变! ③:隔离性(Isolation):如果

MySQL事务学习-->隔离级别

6 事务的隔离级别 设置的目的 在数据库操作中,为了有效保证并发读取数据的正确性,提出的事务隔离级别. 数据库是要被广大客户所共享访问的,那么在数据库操作过程中很可能出现以下几种不确定情况. 更新丢失 两个事务都同时更新一行数据,但是第二个事务却中途失败退出,导致对数据的两个修改都失效了.这是因为系统没有执行任何的锁操作,因此并发事务并没有被隔离开来. 脏读 一个事务开始读取了某行数据,但是另外一个事务已经更新了此数据但没有能够及时提交.这是相当危险的,因为很可能所有的操作都被回滚. 不可重复读

关于不同隔离级别下锁机制的研究

众所周之,隔离级别分为:       Read Uncommited:可以读取提交的记录      ReadCommitted:仅读到提交的数据,会产生幻读现象     Repeatable Read :对读取到的数据加锁,并对读取的范围加锁,不存在幻读现象     Serializable:读加读锁写加写锁,串行执行   情况一:主键(where  主键=???) Read Committed隔离级别 show create table key_id; +--------+----------