MySQL InnoDB中的行锁 Next-Key Lock消除幻读
2017-03-26 16:04
579 查看
InnoDB中有三种行锁技术:
Record Lock:单个行记录上的锁,我们通常讲的行锁,它的实质是通过对索引的加锁实现;只有通过索引条件检索数据,InnoDB才使用行级锁,否则,InnoDB将使用表锁。在事务隔离级别为读已提交下,仅采用Record Lock。
Gap Lock:间隙锁,锁定一个范围,但不包含记录本身;
Next-Key Lock:Record Lock+Gap Lock,锁定一个范围,并且锁定记录本身
如果索引为 10,20,50,那么:
Record Lock:select * from tab where id = 10 for update; //对id=10单行进行加锁
Gap Lock锁范围:(- ∞,10)(10,20)(20,50)(50,+∞)
Next-Key Lock锁范围:(- ∞,10)[10,20)[20,50)[50,+∞)
应该从上面的例子中看出了一些问题。
Next-Key Lock的加锁方式
当查询的索引含有唯一属性时,InnoDB会对Next-Key Lock进行优化,将其降级为Record Lock,即仅锁住索引本身,而不是范围。上表中的第三个事例中可看出.
一般的数据库避免幻读需要在串行化的事务隔离级别下,而InnoDB在可重复读的事务隔离级别下消除幻读;这样能够有效提高数据库的并发度。
具体的例子可以参考第2、3节,不再举例。
参考:
《MySQL技术内幕》
http://blog.csdn.net/mysteryhaohao/article/details/51669741
Record Lock:单个行记录上的锁,我们通常讲的行锁,它的实质是通过对索引的加锁实现;只有通过索引条件检索数据,InnoDB才使用行级锁,否则,InnoDB将使用表锁。在事务隔离级别为读已提交下,仅采用Record Lock。
Gap Lock:间隙锁,锁定一个范围,但不包含记录本身;
Next-Key Lock:Record Lock+Gap Lock,锁定一个范围,并且锁定记录本身
1. Next-Key Lock
Next-Key Lock是结合Record Lock与Gap Lock的一种锁定方法,它锁定了包括记录本身的一个范围。id | name |
---|---|
10 | a |
20 | b |
50 | c |
Record Lock:select * from tab where id = 10 for update; //对id=10单行进行加锁
Gap Lock锁范围:(- ∞,10)(10,20)(20,50)(50,+∞)
Next-Key Lock锁范围:(- ∞,10)[10,20)[20,50)[50,+∞)
事务A | 事务B |
---|---|
set autocommit=0; | |
select * from tab where id>10 for update; //查询结果为20,50 | |
select * from tab where id=10 for update;//执行等待,Next-Key Lock锁机制暴露 | |
commit; | |
继续执行,查询结果为10 | |
select * from tab where id=10 for update; //查询结果为10 | |
select * from tab where id=10 for update; //等待执行 | |
commit; | |
继续执行,查询结果为10 | |
select * from tab where id=10 for update; //查询结果为10,锁降级为Record Lock | |
select * from tab where id>20 for update; //立即执行,查询结果为50 |
Next-Key Lock的加锁方式
当查询的索引含有唯一属性时,InnoDB会对Next-Key Lock进行优化,将其降级为Record Lock,即仅锁住索引本身,而不是范围。上表中的第三个事例中可看出.
2. 为什么会存在Next-Key Lock
InnoDB能在可重复读的事务隔离级别下消除幻读一般的数据库避免幻读需要在串行化的事务隔离级别下,而InnoDB在可重复读的事务隔离级别下消除幻读;这样能够有效提高数据库的并发度。
3. 幻读
幻读是指在同一事务下,连续执行两次同样的SQL语句可能导致不同的结果,第二次的SQL语句可能会返回之前不存在的行。事务A | 事务B |
---|---|
SET SESSION tx_isolation=’READ-COMMITTED’; | |
begin; select * from tab where id>10 for update; //查询结果为20,50 | |
begin; insert into tab values(30,c); commit; | |
select * from tab where id>10 for update; //查询结果为20,30,50;出现幻读 |
4. Next-Key Lock避免幻读
关键点在于对查询范围进行加锁,在另一个事务执行插入操作时是不被运行的,从而避免了幻读。具体的例子可以参考第2、3节,不再举例。
参考:
《MySQL技术内幕》
http://blog.csdn.net/mysteryhaohao/article/details/51669741
相关文章推荐
- MySQL InnoDB锁机制之Gap Lock、Next-Key Lock、Record Lock解析
- Mysql加锁过程详解(8)-理解innodb的锁(record,gap,Next-Key lock)
- Mysql加锁过程详解(8)-理解innodb的锁(record,gap,Next-Key lock)
- MySQL InnoDB锁机制之Gap Lock、Next-Key Lock、Record Lock解析
- MySQL InnoDB四个事务级别 与 脏读、不重复读、幻读
- MySQL中InnoDB引擎的行锁是通过加在什么上完成(或称实现)的?为什么是这样子的
- MySQL的InnoDB的幻读问题
- Innodb锁机制:Next-Key Lock 浅谈
- MySQL的InnoDB的幻读问题
- Mysql(Innodb)如何避免幻读
- MySQL InnoDB四个事务级别 与 脏读、不重复读、幻读
- MySQL InnoDB四个事务级别 与 脏读、不重复读、幻读
- Mysql事务以及四中隔离级别实例2以及InnoDB如何解决当时读的幻读问题
- MySQL的InnoDB默认隔离级别的幻读问题
- 推荐:mysql锁 innodb下的记录锁,间隙锁,next-key锁
- Innodb锁机制:Next-Key Lock 浅谈(转)
- InnoDB: MySQL and InnoDB data dictionaries are out of sync + InnoDB: AUTOINC next value generation
- innodb next-key lock引发的死锁
- 总是忘记的场景:MySQL InnoDB四个事务级别 与 脏读、不重复读、幻读
- [MySQL][Gap Lock][Next-Key Lock]浅析