MYSQL幻读问题

幻读是什么?

“Phantom Problem是指在同一事务下,连续执行两次同样的SQL语句可能导致不同的结果,第二次的SQL语句可能会返回之前不存在的行。”摘录来自 MySQL技术内幕:InnoDB存储引擎(第2版) (数据库技术丛书)

​ 通俗来说就是,time1:事务A读取某个范围,time2:事务B在这个范围中插入了一条新记录并提交事务,time3:事务A再次读取该范围的记录时读取到事务B新增的记录。

如下:

目前InnoDB存储引擎中,数据库有表如下:

-- ----------------------------
-- Table structure for film
-- ----------------------------
DROP TABLE IF EXISTS `film`;
CREATE TABLE `film` (
  `id` int NOT NULL AUTO_INCREMENT,
  `name` varchar(10) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb3;

-- ----------------------------
-- Records of film
-- ----------------------------
BEGIN;
INSERT INTO `film` (`id`, `name`) VALUES (1, 'film1');
INSERT INTO `film` (`id`, `name`) VALUES (2, 'film2');
COMMIT;

Time1: 开启事务A , 查询表film中的所有记录。

MYSQL幻读问题_第1张图片

Time2:在film表中插入一条ID 为 3的记录

MYSQL幻读问题_第2张图片

Time3: 事务A查询表film中所有的数据;注意这时select出的记录中是没有ID为3的记录。

MYSQL幻读问题_第3张图片

但是我们会发现update ID 为3的记录是成功的,也就是说事务A是可以感知到事务B新增的ID为3的记录。

MYSQL幻读问题_第4张图片

这时再去读区数据发现是可以读取到的

MYSQL幻读问题_第5张图片

这就是幻读问题。

如何避免幻读问题?

在RR级别下,采用Next-Key Locking的算法避免幻读问题,即使用FOR UPDATE。

SELECT * FROM film FOR UPDATE;

对于上面的SQL语句,会将(-∞,+∞)这个范围加锁,因此在这个范围内的插入都是不允许的,从而避免幻读。当然如果是id > 2 范围查找那么锁住的也就是(2,+∞)。

你可能感兴趣的:(MySQL优化,mysql,数据库)