幻读是什么?幻读有什么问题

一: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);

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

这条语句会命中d=5这一行,对应主键是id =5 ,这一行会加一个写锁。 由于d 上没有索引,这条语句查询的时候会做全表扫描。但是 不满足条件的5行记录上会不会加锁呢?

二:幻读是什么:

 查询语句用的是当前读,并且加上了些锁。Q3读到id = 1 这一行的现象称为幻读。

1.在可重复读隔离级别下,普通查询是快照读,是不会看到别的事务插入的数据,幻读在当前读下才会出现。

2.sessionb 的修改结果被sessiona读到,不能称为幻读,幻读指的是行插入的行

 幻读有什么问题:

1.语义上的。

sessonA是要给d=5的加锁。但是sessionB ,sessionC 都可以执行成功。sessionA只是给id = 5 加了锁。

2 。破坏了数据一致性

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

 

 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*/

 

 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)*/

 上边把表的所有数据都加了锁,但是还是插入了数据 。

如何解决幻读?

新插入的语句是更新的记录之间的间隙。为了解决这个问题,引入了间隙锁。

产生 了七个间隙 。

select * from t where d= 5 for update;,不止给6个记录加上了行锁。同时还加了7个间隙锁。这样就确保无法插入新的记录。

跟间隙锁存在冲突关系的是往这个间隙中插入一个记录,这个操作。间隙锁之间都不存在冲突关系。

 

这俩条语句都加了 (5,10)这个间隙锁,但是不冲突,不会吧sessionB阻塞住。

select * from t for update 是把整个表的所有记录锁起来。就形成了7个next-key-lock.

 但是也会出现问题。就是会发生死锁;

 可能会引出并发读。

猜你喜欢

转载自www.cnblogs.com/hanguocai/p/10195045.html