InnoDB如何解决幻读的

InnoDB 使用一种称为 Next-Key Locking 的锁机制来解决幻读问题。幻读发生在一个事务在读取某个范围内的记录时,另一个事务在这个范围内插入新的记录。InnoDB 的 Next-Key Locking 结合了行锁(Row Lock)和间隙锁(Gap Lock),确保在执行范围查询时能够锁定现有记录以及它们之间的间隙,从而防止其他事务在该范围内插入新的记录。

Next-Key Locking 机制

Next-Key Locking 是一种在索引记录上应用的锁机制,它锁住的并不仅仅是索引记录本身,还包括索引记录之间的间隙。这种机制可以防止其他事务在锁定的范围内插入新的记录。

具体例子

假设你有一个包含以下记录的表 employees

sql 复制代码
CREATE TABLE employees (
    id INT PRIMARY KEY,
    name VARCHAR(100)
);

INSERT INTO employees (id, name) VALUES (1, 'Alice'), (3, 'Bob'), (5, 'Charlie');

在使用可重复读(REPEATABLE READ)隔离级别时,InnoDB 如何避免幻读?考虑以下两个事务:

  • 事务 A:执行一个范围查询。
  • 事务 B:在事务 A 的范围内插入新的记录。
事务 A
sql 复制代码
START TRANSACTION;
SELECT * FROM employees WHERE id BETWEEN 1 AND 5;

当事务 A 执行上述查询时,InnoDB 会对满足条件的所有记录(id=1, id=3, id=5)以及这些记录之间的间隙((1,3), (3,5), (5,∞))加锁。

事务 B
sql 复制代码
START TRANSACTION;
INSERT INTO employees (id, name) VALUES (2, 'David');

由于事务 A 已经锁定了 id 范围 [1,5] 及其间隙,所以事务 B 尝试在范围 [1,3] 的间隙中插入 id=2 的新记录时会被阻塞,直到事务 A 提交或回滚。

示例演示

创建表和插入数据
sql 复制代码
CREATE TABLE employees (
    id INT PRIMARY KEY,
    name VARCHAR(100)
);

INSERT INTO employees (id, name) VALUES (1, 'Alice'), (3, 'Bob'), (5, 'Charlie');
事务 A
sql 复制代码
START TRANSACTION;
SELECT * FROM employees WHERE id BETWEEN 1 AND 5; -- Next-Key Locking 在索引记录及其间隙上加锁
事务 B
sql 复制代码
START TRANSACTION;
INSERT INTO employees (id, name) VALUES (2, 'David'); -- 此操作会被阻塞,直到事务 A 提交或回滚
提交事务 A
sql 复制代码
COMMIT; -- 提交事务 A 后,事务 B 可以继续执行

总结

InnoDB 使用 Next-Key Locking 机制通过结合行锁和间隙锁来解决幻读问题。当一个事务在执行范围查询时,InnoDB 会锁定查询结果集中的每一条记录以及这些记录之间的间隙。这确保了在范围内的任何插入操作都被阻塞,从而避免了幻读。

这种锁机制在可重复读(REPEATABLE READ)隔离级别下有效地避免了幻读,使得事务在读取范围内的数据时,不会因为其他事务的插入而读取到新的"幻影"记录。

相关推荐
mmsx1 小时前
android sqlite 数据库简单封装示例(java)
android·java·数据库
zpjing~.~2 小时前
Mongo 分页判断是否有下一页
数据库
2401_857600952 小时前
技术与教育的融合:构建现代成绩管理系统
数据库·oracle
秋恬意2 小时前
Mybatis能执行一对一、一对多的关联查询吗?都有哪些实现方式,以及它们之间的区别
java·数据库·mybatis
潇湘秦3 小时前
一文了解Oracle数据库如何连接(1)
数据库·oracle
雅冰石3 小时前
oracle怎样使用logmnr恢复误删除的数据
数据库·oracle
web前端神器3 小时前
mongodb给不同的库设置不同的密码进行连接
数据库·mongodb
从以前3 小时前
Berlandesk 注册系统算法实现与解析
数据库·oracle
Muko_0x7d23 小时前
Mongodb
数据库·mongodb
Ren_xixi3 小时前
redis和mysql的区别
数据库·redis·mysql