innodb幻读问题怎么解决

发布时间:2022-05-12 14:43:24 作者:iii
来源:亿速云 阅读:180

本篇内容主要讲解“innodb幻读问题怎么解决”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“innodb幻读问题怎么解决”吧!

1.幻读

CREATE TABLE `test_20` ( `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 test_20 values(0,0,0),(5,5,5),(10,10,10),(15,15,15),(20,20,20),(25,25,25);
begin;select * from t where d=5 for update;commit;

这个语句会命中 d=5 的这一行,对应的主键 id=5,因此在 select 语句执行完成后,id=5 这一行会加一个写锁,而且由于两阶段锁协议,这个写锁会在执行 commit 语句的时候释放。

如果只在 id=5 这一行加锁,而其他行的不加锁的话,会怎么样?

innodb幻读问题怎么解决

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

说明:

2.幻读的问题(更新与新增)

2.1 语义上

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

2.2 数据一致性问题

锁的设计是为了保证数据的一致性。而这个一致性,不止是数据库内部数据状态在此刻的一致性,还包含了数据和日志在逻辑上的一致性。

innodb幻读问题怎么解决

候 binlog 里面的内容:

放在一起如下:

update t set d=5 where id=0; /*(0,0,5)*/update t set c=5 where id=0; /*(0,5,5)*/insert into t values(1,1,5); /*(1,1,5)*/update t set c=5 where id=1; /*(1,5,5)*/update t set d=100 where d=5;/* 所有 d=5 的行,d 改成 100*/

这个语句序列,不论是拿到备库去执行,还是以后用 binlog 来克隆一个库,这三行的结果,都变成了 (0,5,100)、(1,5,100) 和 (5,5,100)。

原因是:

进一步假设:

innodb幻读问题怎么解决

binlog 里面执行序列:

insert into t values(1,1,5); /*(1,1,5)*/update t set c=5 where id=1; /*(1,5,5)*/update t set d=100 where d=5;/* 所有 d=5 的行,d 改成 100*/update t set d=5 where id=0; /*(0,0,5)*/update t set c=5 where id=0; /*(0,5,5)*/

这里解决了session B的问题,但是session C新增的问题并没有解决!

在 T3 时刻,我们给所有行加锁的时候,id=1 这一行还不存在,不存在也就加不上锁。也就是说,即使把所有的记录都加上锁,还是阻止不了新插入的记录。

3.InnoDB 怎么解决幻读的问题

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

间隙锁,锁的就是两个值之间的空隙。比如表 test_20,初始化插入了 6 个记录,这就产生了 7 个间隙。

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

数据行是可以加上锁的实体,数据行之间的间隙,也是可以加上锁的实体。但是间隙锁跟我们之前碰到过的锁都不太一样。

3.1 带来的问题

innodb幻读问题怎么解决

至此,两个 session 进入互相等待状态,形成死锁。间隙锁的引入,可能会导致同样的语句锁住更大的范围,这其实是影响了并发度的。

解决方法:

到此,相信大家对“innodb幻读问题怎么解决”有了更深的了解,不妨来实际操作一番吧!这里是亿速云网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

推荐阅读:
  1. 解决MySQL幻读方法简析
  2. 如何解决MySQL的幻读问题

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

innodb

上一篇:php工厂模式怎么实现

下一篇:php中的Redis和Memcached怎么用

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》