什么是幻读

2021-07-23 14:28:28 浏览数 (2)

什么是幻读

1. 举个例子

定义表结构如下:

代码语言:javascript复制
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);
  • T1 时刻查询到的数据为id=5这行数据
  • T2 时刻将id=0的数据的d置为5
  • T3 时刻查询到的数据为id=0,id=5的数据
  • T4时刻插入新的数据 (1,1,5)
  • T5时刻查询到的数据为id=0,id=1,id=5,

其中T5时刻查询到了id=1的现象称为幻读,而查到id=0不能称为幻读。这是因为幻读的定义为幻读指的是两次查询同一个范围的数据,后一次查询到了前一次没有查询到的数据,就好像出现了幻觉,所以称为幻读。需要注意的是,幻读只有在当前读的时候才会出现,而且幻读专指新插入的行

2. 幻读带来的问题

  • 破坏了锁的语义。当实行 select ... from... where ... for update 的时候,语义是要锁住符合条件的行,但是幻读破坏了这个规则。
  • 数据不一致。两次同样的范围查询却查出来的结果不一样。

3. 如何解决幻读

答案是使用间隙锁。在两两数据行之间有间隙,如果我们能把数据行之间的间隙也锁住,则不会有产生幻读的数据插入。

间隙锁和行锁合称为next-key lock ,实现语句为 select * from t for update。这样表t中数据行被锁住,而且行与行之间的间隙也会被锁住。

4. next-key lock 带来的问题

next-key lock 会导致锁的范围变大,影响并发,而且有可能会带来死锁。

0 人点赞