精华内容
下载资源
问答
  • 2021-11-14 15:00:03

    事务的并发问题

    1. 脏读:事务A读取了事务B更新的数据,然后B回滚操作,那么A读取到的数据是脏数据
    2. 不可重复读:事务A多次读取同一数据,事务B在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同一数据时,结果不一致。
    3. 幻读:A事务读取了B事务已经提交的新增数据。注意和不可重复读的区别,这里是新增,不可重复读是更改(或删除)。select某记录是否存在,不存在,准备插入此记录,但执行 insert 时发现此记录已存在,无法插入,此时就发生了幻读。

    MySQL如何实现避免幻读

    • 在快照读读情况下,MySQL通过MVCC来避免幻读。
    • 在当前读读情况下,MySQL通过next-key来避免幻读

    什么是MVCC

    MVCC全称是多版本并发控制的简称(multi version concurrent control)。MySQL把每个操作都定义成一个事务,每开启一个事务,系统的事务版本号自动递增。每行记录都有两个隐藏列:创建版本号和删除版本号

    MVCC多版本并发控制是MySQL中基于乐观锁理论实现隔离级别的方式,用于读已提交和可重复读取隔离级别的实现。

    在MySQL中,会在表中每一条数据后面添加两个字段:最近修改该行数据的事务ID,指向该行(undolog表中)回滚段的指针。

    Read View判断行的可见性,创建一个新事务时,copy一份当前系统中的活跃事务列表。意思是,当前不应该被本事务看到的其他事务id列表。已提交读隔离级别下的事务在每次查询的开始都会生成一个独立的ReadView,而可重复读隔离级别则在第一次读的时候生成一个ReadView,之后的读都复用之前的ReadView。

    • select:事务每次只能读到创建版本号小于等于此次系统版本号的记录,同时行的删除版本号不存在或者大于当前事务的版本号。

    • update:插入一条新记录,并把当前系统版本号作为行记录的版本号,同时保存当前系统版本号到原有的行作为删除版本号。

    • delete:把当前系统版本号作为行记录的删除版本号

    • insert:把当前系统版本号作为行记录的版本号

    什么是next-key锁

    InnoDB 采用 Next-Key Lock 解决幻读问题。

    insert into test(xid) values (1), (3), (5), (8), (11)
    

    在这条语句执行后,由于xid上是有索引的,该算法总是会去锁住索引记录
    现在,该索引可能被锁住的范围如下:(-∞, 1], (1, 3], (3, 5], (5, 8], (8, 11], (11, +∞)。

    select * from test where id = 8 for update
    

    这条语句执行后会锁住的范围:(5, 8], (8, 11]。
    除了锁住8所在的范围,还会锁住下一个范围,所谓Next-Key。

    更多相关内容
  • mysql如何防止幻读

    千次阅读 2022-03-11 13:52:53
    MySQL 事务都是指在 InnoDB 引擎下,MyISAM 引擎是不支持事务的。 事务具有原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)四个特性,简称 ACID,缺一不可。今天要说的就是...

    前言

    以下内容是作者在网上搜集和自己总结而来。

    一、基本概念

    MySQL 事务都是指在 InnoDB 引擎下,MyISAM 引擎是不支持事务的。

    事务具有原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)四个特性,简称 ACID,缺一不可。今天要说的就是隔离性。

    1.1 脏读

    脏读指的是读到了其他事务未提交的数据,未提交意味着这些数据可能会回滚,也就是可能最终不会存到数据库中,也就是不存在的数据。读到了并一定最终存在的数据,这就是脏读。

    1.2 可重复读

    可重复读指的是在一个事务内,最开始读到的数据和事务结束前的任意时刻读到的同一批数据都是一致的。通常针对数据更新(UPDATE)操作。

    1.3 不可重复读

    对比可重复读,不可重复读指的是在同一事务内,不同的时刻读到的同一批数据可能是不一样的,可能会受到其他事务的影响,比如其他事务改了这批数据并提交了。通常针对数据更新(UPDATE)操作。

    1.4 幻读

    幻读是针对数据插入(INSERT)操作来说的。假设事务A对某些行的内容作了更改,但是还未提交,此时事务B插入了与事务A更改前的记录相同的记录行,并且在事务A提交之前先提交了,而这时,在事务A中查询,会发现好像刚刚的更改对于某些数据未起作用,但其实是事务B刚插入进来的,让用户感觉很魔幻,感觉出现了幻觉,这就叫幻读。

    二、事务隔离级别

    SQL 标准定义了四种隔离级别,MySQL 全都支持。这四种隔离级别分别是:

    2.1 读未提交(READ UNCOMMITTED)

    最低的事务隔离级别,一个事务还没提交时,它做的变更就能被别的事务看到;

    2.2 读提交 (READ COMMITTED)

    保证一个事物提交后才能被另外一个事务读取。另外一个事务不能读取该事物未提交的数据,可避免脏读的发生,但是可能会造成不可重复读;

    2.3 可重复读 (REPEATABLE READ)

    多次读取同一范围的数据会返回第一次查询的快照,即使其他事务对该数据做了更新修改。事务在执行期间看到的数据前后必须是一致的,但如果这个事务在读取某个范围内的记录时,其他事务又在该范围内插入了新的记录,当之前的事务再次读取该范围的记录时,会产生幻行,这就是幻读;

    2.4 串行化 (SERIALIZABLE)

    花费最高代价但最可靠的事务隔离级别。

    “写”会加“写锁”,“读”会加“读锁”。当出现读写锁冲突的时候,后访问的事务必须等前一个事务执行完成,才能继续执行

    只有串行化的隔离级别解决了全部这 3 个问题,其他的 3 个隔离级别都有缺陷。
    从上往下,隔离强度逐渐增强,性能逐渐变差。采用哪种隔离级别要根据系统需求权衡决定,其中,可重复读是 MySQL 的默认级别。

    事务隔离其实就是为了解决上面提到的脏读、不可重复读、幻读这几个问题,下面展示了 4 种隔离级别对这三个问题的解决程度。
    在这里插入图片描述
    只有串行化的隔离级别解决了全部这 3 个问题,其他的 3 个隔离级别都有缺陷。

    三、快照读-MVCC

    3.1 什么是MVCC

    MVCC,全称Multi-Version Concurrency Control,即多版本并发控制。MVCC是一种并发控制的方法,一般在数据库管理系统中,实现对数据库的并发访问,在编程语言中实现事务内存。

    MVCC在MySQL InnoDB中的实现主要是为了提高数据库并发性能,用更好的方式去处理读-写冲突,做到即使有读写冲突时,也能做到不加锁,非阻塞并发读

    3.2 什么是快照读

    像不加锁的select操作就是快照读,即不加锁的非阻塞读;快照读的前提是隔离级别不是串行级别,串行级别下的快照读会退化成当前读;之所以出现快照读的情况,是基于提高并发性能的考虑,快照读的实现是基于多版本并发控制,即MVCC,可以认为MVCC是行锁的一个变种,但它在很多情况下,避免了加锁操作,降低了开销;既然是基于多版本,即快照读可能读到的并不一定是数据的最新版本,而有可能是之前的历史版本

    3.3 快照读的实现方式

    MVCC中的核心知识点
    (1)事务版本号
    每次事务开启前都会从数据库获得一个自增长的事务ID,可以从事务ID判断事务的执行先后顺序。
    (2)表的隐藏列
    DB_TRX_ID: 记录操作该数据事务的事务ID;
    DB_ROLL_PTR:指向上一个版本数据在undo log 里的位置指针;
    DB_ROW_ID: 隐藏ID ,当创建表没有合适的索引作为聚集索引时,会用该隐藏ID创建聚集索引;
    (3)undo log
    Undo log 主要用于记录数据被修改之前的日志,在表信息修改之前先会把数据拷贝到undo log 里,当事务进行回滚时可以通过undo log 里的日志进行数据还原。
    在这里插入图片描述
    (4)read view
    在innodb 中每个SQL语句执行前都会得到一个read_view。副本主要保存了当前数据库系统中正处于活跃(没有commit)的事务的ID号,其实简单的说这个副本中保存的是系统中当前不应该被本事务看到的其他事务id列表。
    min_trx_id:read view生成时,活跃事务id列表中的最小id
    max_trx_id:read view生成时,数据库即将分配的事务id,也就是当前已创建最大事务id+1
      一个事务在对一行数据做读取操作的时候,会从undo log历史版本链中从最新版本开始往前比对,通过一系列的规则,根据快照版本中的trx_id字段和read view来确定该版本对于当前事务是否可见,如果当前比对版本不可见,那么就通过roll_pointer找到上一个版本进行比对,直到找到可见版本或找不到任何一个可见版本。这些规则定义如下:

    1.如果 trx_id < min_trx_id,则说明该版本对于当前事务(read view)来说,是已提交事务生成的,那么对于当前事务可见。
    2.如果trx_id >= max_trx_id:则说明说明该数据是在当前read view 创建之后才产生的,所以数据不予显示。3.如果min_trx_id =< trx_id < max_trx_id:
    这种情况就说明这个数据有可能是在当前事务开始的时候还没有提交的。所以这时候我们需要把数据的事务ID与当前read view 中的活跃事务集合trx_ids 匹配:
    情况1: 如果事务ID不存在于trx_ids 集合(则说明read view产生的时候事务已经commit了),这种情况数据则可以显示。
    情况2: 如果事务ID存在trx_ids则说明read view产生的时候数据还没有提交,但是如果数据的事务ID等于creator_trx_id ,那么说明这个数据就是当前事务自己生成的,自己生成的数据自己当然能看见,所以这种情况下此数据也是可以显示的。
    情况3: 如果事务ID既存在trx_ids而且又不等于creator_trx_id那就说明read view产生的时候数据还没有提交,又不是自己生成的,所以这种情况下此数据不能显示。
    在这里插入图片描述
    在这里插入图片描述
    思考下面一个问题:

    在RC(读已提交)和RR(可重复度)级别下,MVCC都会生效,那么为什么RC不可以解决幻读,而RR可以解决幻读?

         原因: 两种隔离界别下的核心处理逻辑就是判断所有版本中哪个版本是当前事务可见的处理。针对这个问题InnoDB在设计上增加了ReadView的设计,ReadView中主要包含当前系统中还有哪些活跃的读写事务,把它们的事务id放到一个列表中,我们把这个列表命名为为m_ids。
    
         以上内容是对于 RR 级别来说,而对于 RC 级别,其实整个过程几乎一样,唯一不同的是生成 ReadView 的时机,RR 级别只在事务开始时生成一次,之后一直使用该 ReadView。而 RC 级别则在每次 select 时,都会生成一个 ReadView。
    

    四、当前读-锁

    4.1 锁介绍

    当前读是读取的数据库最新的数据,当前读和快照读不同,因为要读取最新的数据而且要保证事务的隔离性,所以当前读是需要对数据进行加锁的,当前读的实现方式就是Next key lock临键锁。

    临键锁(Next-key Locks)
    临键锁,是记录锁与间隙锁的组合,它的封锁范围,既包含索引记录,又包含索引区间

    记录锁(Record Locks)
    记录锁是 封锁记录,记录锁也叫行锁,例如:
    SELECT * FROM student WHERE id=1 FOR UPDATE;
    它会在 id=1 的记录上加上记录锁,以阻止其他事务插入,更新,删除 id=1 这一行。

    间隙锁(Gap Locks)
    间隙锁是封锁索引记录中的间隔,或者第一条索引记录之前的范围,又或者最后一条索引记录之后的范围.

    4.2 产生间隙锁条件

    在这里插入图片描述

    4.3 加锁规则

    在这里插入图片描述

    4.4 案例数据

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    4.5 临键锁

    在这里插入图片描述

    总结

    在这里插入图片描述

    思考

    MVCC真的解决了幻读问题吗?
    在这里插入图片描述
    在这里插入图片描述

    展开全文
  • 但是对于幻读,我发现在可重复读的隔离级别下没有出现,当时想到难道是MySQL幻读做了什么处理? 测试: 创建一张测试用的表dept: CREATE TABLE `dept` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` ...
  • mysql可重复读和幻读的理解可重复读和幻读的定义最后总结参考资料 很多教程和书籍对mysql的可重复读和幻读的解释都比较含糊,本文结合原理和其他的考证,深入分析下。 这里讨论的引擎是常用的InnoDB。 可重复读和...
  • 这里,需要对幻读做一个说明: 1、mysql在可重复读级别下,普通的查询(select * from t where id=5)是快照读,是不会看到别的事务插入的数据的的, 因此“幻读”在“当前读”下才会出现。 2、上面sessionB的修改...

    一、前言

           建表语句和初始化语句如下:

    CREATE TABLE `t`(
        `id` int(11) NOT NULL,
    	`c`  int(11) DEFAULT NULL,
    	`d`  int(11) DEFAULT NULL,
    	PRIMARY KEY(`id`),
    	KEY `c`(`c`)
    )ENGINE=InnoDB;
    insert into t values(0,0,0),(5,5,5),(10,10,10),(15,15,15),(20,20,20),(25,25,25);

           这个表除了主键id外,还有1个索引C,初始化语句在表中插入6行数据。

           下面的语句是怎么加锁的?加的锁又是什么时候释放的?

    begin;
    select * from t where d = 5 for update;
    commit;

          比较好理解的是,这个语句会命中d=5这一行,对应的主键id=5,因此在select语句执行之后,id=5这一行记录会加一个写锁,而且由于两阶段锁协议,这个写锁,会在执行commit语句的时候释放。

          由于字段d上没有索引,因此这条查询会做全表扫描,那么其他被扫描到的,但是不满足条件的5行记录上,会不会加锁呢?

          众所周知,InnoDB默认的隔离级别是可重复读,所以本文在没有特殊说明的前提下,都是设定在可重复读隔离级别下的。

    二、幻读是什么?

           如果只在id=5,这一行加锁,而其他行不加锁的话,会怎么样呢?首先看一下这个场景。

                          

            可以看到session A里面执行了3次查询。分别是Q1、Q2和Q3。它们的sql相同,都是select * from t where d=5 for update;这条语句的意思是查所有d=5的行,而且使用的是当前读。并且加上写锁。接下来看下这三条SQL语句,会返回什么结果?

            1、Q1只返回id=5的这一行;

            2、在T2时刻,sessionB把id=0这一行的d值改成了5,因此T3时刻Q2查出来的是id=0和id=5这两行。

            3、 在T4时刻,sessionC又插入了一行(1,1,5)。因此T5时刻Q3查出来的是id=0、id=1和id=5这三行。

            其中,在T5时刻Q3读到id=1这一行的现象,被称为“幻读”。也就是说幻读指的是一个事务在前后两次查询同一范围的时候,后一次查询看到了前一次查询没有看到的值。

            这里,需要对幻读做一个说明:

            1、mysql在可重复读级别下,普通的查询(select * from t where id=5)是快照读,是不会看到别的事务插入的数据的的, 因此“幻读”在“当前读”下才会出现。

            2、上面sessionB的修改结果,被sessionA之后的select语句用“当前读”看到,不能成为幻读。幻读仅专指“新插入的行”

    三、幻读有什么问题?

           1、首先是语义上的。sessionA在T1时刻就声明了,“我要把所有id=5的行锁住,不准别的事务进行读写操作”。而实际上,这个语义被破坏了。

           2、其次是数据一致性的问题。这个数据不一致到底是怎么引入的?

    四、如何解决幻读?

           产生幻读的原因是,行锁只能锁住行,但是新插入记录的这个动作,要更新的是记录之间的“间隙”。因此,为了解决幻读问题,InnoDB只好引入新的锁,也就是间隙锁(Gap Lock)。

           顾名思义,锁的就是两个值之间的空隙。如开头时的表t,初始化插入了6条记录。这就产生了7个间隙。

                                    

           当你执行select * from t where d=5 for update的时候,就不止是给数据库中已有的6个记录加上行锁,还同时加上了7个间隙锁。这样就确保无法再插入新记录。 也就是说在一行行的扫描过程中,不仅给行加上了行锁,还给行2边的空隙加上了间隙锁。

           间隙锁和行锁合称next-key lock,每个next-key lock都是前开后闭区间。也就是说,我们的表t初始化之后,如果用select * from t for update  要把整个表所有记录锁起来,就形成了7个next-key lock。分别是(-∞,0]、(0,5]、(5,10]、(10,15]、(15,20]、(20,25]、(25,supremum]。我们把间隙锁标记为开区间,把next-key lock标记为闭区间。

    五、间隙锁导致死锁?       

                            

          1、session A执行select ... for update语句,由于id=9这一行并不存在,因此会加上间隙锁(5,10)。

          2、session B执行select ... for update语句,同样会加上间隙锁(5,10)。间隙锁之间不会冲突,因此这个语句可以执行成功。

          3、session B试图插入一行(9,9,9),被session A的间隙锁挡住,只好进入等待状态。

          4、session A试图插入一行(9,9,9,),被session B的间隙锁挡住了。

          此时,两个session进入了相互等待状态,形成了死锁。当然InnoDB的死锁检测机制马上就发现了这对死锁,让sessionA的insert语句报错返回啦。间隙锁的引入,可能导致同样的语句,锁住了更大的范围。这其实是影响了并发度的。

          如果将隔离级别设置为读提交,就没有间隙锁了。一些公司使用读提交+ binlog_format=row的组合。这样配置是否合理呢?配置是否合理,跟业务场景有关,需要具体问题具体分析。比如说,如果大家都用读提交,可是逻辑备份的时候,mysqldump要把备份线程设置为可重复读。然后,在备份期间,备份线程用的是可重复读,而业务线程用的是读提交。同时存在两种事务隔离级别,会不会有问题呢?

    六、注释

        1、两阶段锁协议:

        先举个例子,在下面的操作序列中,事务B的update语句执行时会是什么现象呢?假设字段id是表t的主键。根间隙锁存在冲突关系的,是“往这个间隙中插入1个记录”这个操作,间隙锁之间都不存在冲突关系。

                                                 

           这个问题的结论取决于事务A在执行完两条update语句后,持有哪些锁,以及在什么时候释放。可以验证一下,实际上事务B的update语句会被阻塞,知道事务A执行Commit之后,事务B才能执行。事务A持有的两条记录的行锁,都是在commit的时候才释放的,也就是说,在InnoDB事务中,行锁在需要的时候才加上的,但并不是不需要了就立刻释放,而是要等到事务结束时才释放,这个就是两阶段锁协议

        2、当前读和快照度

         ① 快照读(snapshot read):简单的select语句(不包括select ... lock in share mode(共享锁),select ... for update(排它锁)) 

         ② 当前读(current read) :

      select ... lock in share mode
    
      select ... for update
    
      insert
    
      update 
    
      delete 

      七、面试回答间隙锁的相关引申

    相关知识: 间隙锁——>快照读——>行锁——>共享锁、排他锁——乐观锁、悲观锁。

    解决幻读问题?

    id d

    1 1

    5 5

    10 10

     

    select * from T where 1<=id<=5

     

    对于当前读而言, 1、lock in share mode 2、for update

    1、假如只有行锁,锁住的是id=1和id=的这两条。间隙锁的存在导致不能插入 id值为2,3,4的记录。

     

    2、从乐观锁、悲观锁的角度而言,lock in share mode for update 都是悲观锁。乐观锁、悲观锁仅仅是一个概念。刚刚说的是mysql层面的乐观锁、悲观锁。也可以扩展到java层面的乐观锁、悲观锁。比如synchronized和CAS(compareandswap)

    从另一个角度而言,lock in share mode叫作共享锁,也叫做读锁。for update 叫作排他锁。

         

          

     

    展开全文
  • 三、MySQL 是如何解决幻读的 如果你看到了这篇文章,那么我会默认你了解了 脏读 、不可重复读与可重复读。 1. 多版本并发控制(MVCC)(快照读) 多数数据库都实现了多版本并发控制,并且都是靠保存数据快照来实现的...
  • MySQL解决幻读详解

    千次阅读 2022-04-03 14:25:23
    简单来说就是通过mvcc + ...在快照读的情况下,会通过mvcc来避免幻读 在当前读的情况下,会通过next-key来避免幻读 快照读与当前读 快照读:所有普通的select语句都算快照读,它并不会给表中任何记录做加锁操作,其

    简单来说就是通过mvcc + next-key locks 防止幻读

    幻读是什么?

    当前事务读取了一个范围的记录,另一个事务在该范围内插入了新记录,当前事务再次读取该范围内的记录就会发现新插入的记录,这就是幻读

    以下MySQL的隔离界别都是可重复读(RR)

    mvcc与next-key分别在什么情况下起作用?

    1. 在快照读的情况下,会通过mvcc来避免幻读
    2. 在当前读的情况下,会通过next-key来避免幻读

    快照读与当前读

    1. 快照读:所有普通的select语句都算快照读,它并不会给表中任何记录做加锁操作,其他事务可以对表中记录做任何改动

    2. 当前读:加锁的操作都叫当前读,分为s锁,x锁

      • 共享锁:S锁。在事务要读取一条记录时,需要先获取该记录的S锁

        select … lock in share mode

      • 独享锁(排他锁):X锁。事务要改动一条记录时,需要先获取X锁

        select … for update、insert、update、delete

        S锁与S锁是兼容的;S锁与X锁是不兼容;X锁与X锁也是不兼容。

    简单了解下跟防止幻读有关的行级锁

    1. record locks:把当前记录上锁

    2. gap locks:如果当前列具有唯一索引,那么就仅仅是把当前行加锁;只有当前列没有索引或者具有非唯一索引,才会锁定前面的间隙

    什么意思呢?

    如下例:

    CREATE TABLE `user` (
     `id` int NOT NULL,
     `score` int DEFAULT NULL,
     PRIMARY KEY (`id`)
    ) ENGINE=InnoDB;
    insert into user values(1,79),(3,91),(6,59);
    

    在这里插入图片描述

    事务1事务2
    1begin;
    select * from user where score=91 for update;
    2begin;
    insert into user values(2,98); // 因为gap锁的原因,插入失败
    commit;
    3commit;

    也就是在 id (1, 3) 之间加x锁

    而如果把事务1的查询语句改成

    select * from user where id=3 for update;
    

    则前面的间隙不会上锁,事务2会成功插入!

    1. next-key locks:就是record locks跟gap locks的组合,既能保护该条记录,又能防止其他事务插入该记录前面的间隙中。

      如上述加x锁的区间就变成了 (1, 3]

    简单了解下mvcc

    1. 具有三个隐藏字段:

      • DB_TRX_ID:记录最后进行插入、更新操作的事务

      • DB_ROLL_PTR:滚动指针,指向修改前的记录

      • DB_ROW_ID:如果没有聚簇索引,该字段会构建聚簇索引(相当于隐藏的自增主键)

    2. readview:会记录当前活跃事务的id范围,根据事务id来判断哪个版本是对当前事务可见的

      如下例(还是上面表,默认三条数据):

    事务1事务2
    1begin;
    update user set score=50 where id=1;
    update user set score=60 where id=1;
    2begin;
    select * from user where id=1; //score=79
    3commit;
    4select * from user where id=1; //score=79
    commit;

    ​ 为什么?

    ​ 假设事务1的事务id是100

    1. **事务1未提交:**事务2在执行select之前会生成一个readview,活跃的只有事务1,该readview的事务范围就是100,在该范围内都不符合要求。根据滚动指针(DB_ROLL_PTR)找之前的版本,直到事务id小于100,也就是找到事务1开启之前的版本,那时的score就是79
    DB_TRX_ID(事务id)idscoreDB_ROLL_PTR(滚动指针)
    11001602
    21001503
    380(肯定小于100)179
    1. 事务1提交:
      • 上述的例子是在MySQL默认隔离级别(RR)下,在该隔离级别下,只在第一次select前生成一个readview。在事务1未提交之前已经生成过了,所以搜索到的score还是79。
      • 如果隔离级别是RC,那么第二次select前会再次生成一个readview,那么score就是60

    上面内容过一遍后,在回过头来考虑幻读问题,这不就已经解决了嘛!

    • 快照读的情况下,通过mvcc来避免幻读
    • 当前读的情况下,通过next-key来避免幻读
    展开全文
  • 三、MySQL 是如何解决幻读的 1. 多版本并发控制(MVCC)(快照读) 多数数据库都实现了多版本并发控制,并且都是靠保存数据快照来实现的。 以 InnoDB 为例,每一行中都冗余了两个字段。一个是行的创
  • 发现在客户端B中插入的数据显示出来了,说明客户端A在事务执行期间,客户端B对该表的操作并不会对客户端A有影响,避免幻读。出现这种情况的主要原因是 MySQL 的存储引擎通过多版本并发控制 MVCC 机制解决
  • MySQL 可重复读隔离级别与幻读

    千次阅读 2022-03-16 17:40:02
    MySQL可重复读的隔离级别下,能很大程度上避免幻读,而不能完全避免。 场景复现 环境信息: MySQL版本:5.7.23-log 隔离级别:REPEATABLE-READ 测试数据: SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; --...
  • mysql MVCC不能避免幻读

    2021-04-15 12:56:52
    幻读 并发情况下,A事务读取了一条记录,此时B事务插入一条记录,A事务又读取,读到了两条数据,此时就造成了读取数据不一致,...既然读快照信息,那么是不是MVCC就可以避免幻读,因为事务已经有了快照数据,如果这样
  • 初学MySQL幻读

    2019-08-15 09:59:49
    幻读幻读幻读的问题解决幻读总结 幻读 看一下下面的场景: 假设只在id=5这一行加行锁,来看一下Q1、Q2、Q3的返回结果。 Q1只返回了id=5这一行; T2时刻,session B 把 id=0 这一行的 d 值改成了 5,因此 T3 时刻 Q2...
  • MySQL幻读是如何解决的

    千次阅读 2022-04-10 17:39:46
    在我们的数据库隔离级别中幻读的解决是在串行化的级别下进行处理的,虽然这种方法可以解决幻读,但是这种方法在高并发下效率是非常低的,经过学习了解到两种解决幻读的方法:加间隙锁和MVCC。 加间隙锁 间隙锁:将...
  • MySQL幻读现象

    千次阅读 多人点赞 2019-07-07 19:22:59
    幻读:即由"可重复读"隔离级别引发的事务问题,有些人说幻读就是一次事务中读取到的数据条数不一样,我不太认可这句话,当然这句话并没有什么问题,但是由初学者来理解的话很容易进误区! 幻读场景:银行A开启了一...
  • 一、什么是幻读在一次事务...三、MySQL 是如何解决幻读的如果你看到了这篇文章,那么我会默认你了解了脏读 、不可重复读与可重复读。1. 多版本并发控制(MVCC)(快照读/一致性读)多数数据库都实现了多版本并发控制,并...
  • Mysql如何解决幻读

    千次阅读 2021-07-17 08:52:20
    在一次事务里面,多次查询之后,结果集的个数不一致的情况叫做幻读。而多或者少的那一行被叫做幻行,也就是说当一个事务在进行读取数据的时候,其他事务对该数据进行了改变。在高并发数据库系统中,需要保证事务与...
  • mysql幻读出现的原因及解决方案

    千次阅读 2021-04-22 11:45:55
    今天分享 mysql幻读出现的原因及解决方案: 一、首先明确什么是幻读:​事务A按照一定条件进行数据读取,期间事务B插入了相同搜索条件的新数据,事务A再次按照原先条件进行读取操作修改时,发现了事务B新插入的...
  • 一、什么是幻读在一次事务里面,...三、MySQL 是如何解决幻读的如果你看到了这篇文章,那么我会默认你了解了脏读、不可重复读与可重复读。1. 多版本并发控制(MVCC)(快照读/一致性读)多数数据库都实现了多版本并发控...
  • MySQL 幻读的理解

    2022-01-29 17:43:55
    这里写自定义目录标题欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、...
  • 幻读:前后多次读取,数据总量不一致。 即使把所有的记录都加上锁,还是阻止不了新插入的记录,这是因为给行加锁的时候,这条记录还不存在,没法加锁。 解决方案:间隙锁 (Gap Lock) 间隙锁:在一行行扫描的过程...
  • 事务的特性:原子性:指处于同一个事务中的多条语句是不可分割的。一致性:事务必须使数据库从一个一致...事务隔离性问题:如果不考虑事务的隔离性,会出现以下问题:脏:指一个线程中的事务读取到了另外一个线程...
  • 什么是幻读幻读指的是一个事务在前后两次查询同一个范围的时候,后一次查询看到了前一次查询没有看到的行。 首先快照读是不存在幻读的,只有当前读(实时读)才存在幻读的问题。 幻读有什么问题? select ......
  • MySQL幻读实验

    千次阅读 2022-01-28 15:07:38
    问题 MySQL隔离级别介绍: back-to-basics-isolation-levels-in-...REPEATABLE READ 可重复读,但会带来幻读问题: 然而,我去做一下实验,发现并不是这样的 实验 MySQL版本 8.0.27 CREATE TABLE `userinfo` ( `id`
  • Mysql(Innodb)如何避免幻读

    万次阅读 多人点赞 2016-12-19 10:23:06
    幻读Phantom Rows The so-called phantom problem occurs within a transaction when the same query produces different sets of rows at different times. For example, if a SELECT is executed twice, but ...
  • mysql的MVCC机制在可重复读隔离级别下可以避免部分幻读情况,但是不能完全避免幻读的出现。在快照读情况下,可重复读可以避免幻读。在当前读情况下,可重复读还是会出现幻读,要串行化级别才能解决幻读问题。
  • MySQL是如何解决幻读

    2021-12-02 16:01:25
    MySQL是如何解决幻读
  • MySQL幻读详解及解决方法

    千次阅读 2021-04-03 10:04:00
    1. 什么是幻读? 建立一张表如下: 按照下面步骤执行两个事务。 事务1: 事务2: 由此,可以把幻读理解为:select 某记录是否存在,不存在,准备插入此记录,但执行 insert 时发现此记录已存在,无法插入,此时就...
  • Mysql可重复读隔离级别下如何解决幻读一些概念具体加锁说明使用主键索引进行等值查询使用主键索引进行范围查询使用二级索引进行等值查询使用二级索引进行范围查询 一些概念 幻读:在一次事务中,同一条select语句在...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 54,127
精华内容 21,650
关键字:

mysql如何避免幻读

mysql 订阅