30 | 答疑文章(二):用动态的观点看加锁
该思维导图由 AI 生成,仅供参考
不等号条件里的等值查询
- 深入了解
- 翻译
- 解释
- 总结
本文深入探讨了InnoDB的加锁规则,通过具体案例分析和读者提问,动态解析了加锁过程。文章首先回顾了加锁规则,包括next-key lock作为基本单位、访问对象才会加锁等内容。随后,通过查询案例分析了不等号条件中的等值查询和并发执行可能出现的死锁问题。文章还展示了通过执行show engine innodb status命令得到的死锁现场信息,并推导出了死锁的原因和解决方法。通过这些案例分析,读者可以深入了解InnoDB加锁规则的实际应用和可能遇到的并发问题,为他们在实际开发中避免类似问题提供了有益的参考。文章内容丰富,深入浅出,对于想深入了解MySQL原理的读者具有很高的参考价值。
《MySQL 实战 45 讲》,新⼈⾸单¥68
全部留言(96)
- 最新
- 精选
- 令狐少侠置顶有个问题想确认下,在死锁日志里,lock_mode X waiting是间隙锁+行锁,lock_mode X locks rec but not gap这种加but not gap才是行锁? 老师你后面能说下group by的原理吗,我看目录里面没有
作者回复: 对, 好问题 lock_mode X waiting表示next-key lock; lock_mode X locks rec but not gap是只有行锁; 还有一种 “locks gap before rec”,就是只有间隙锁;
2019-01-22293 - Ryoma置顶删除数据,导致锁扩大的描述:“因此,我们就知道了,由于 delete 操作把 id=10 这一行删掉了,原来的两个间隙 (5,10)、(10,15)变成了一个 (5,15)。” 我觉得这个提到的(5, 10) 和 (10, 15)两个间隙会让人有点误解,实际上在删除之前间隙锁只有一个(10, 15),删除了数据之后,导致间隙锁左侧扩张成了5,间隙锁成为了(5, 15)。
作者回复: 嗯 所以我这里特别小心地没有写“锁“这个字。 间隙 (5,10)、(10,15)是客观存在的。 你提得也很对,“锁”是执行过程中才加的,是一个动态的概念。 这个问题也能够让大家更了解我们标题的意思,置顶了哈 👍
2019-01-2212157 - IceGeek17老师,新年好,有几个问题: 问题一: 对于文中的第一个例子(不等号条件里的等值查询),当试图去找 “第一个id<12的值"的时候,用的还是从左往右的遍历(因为用到了优化2),也就是说,当去找第一个等值的时候(通过树搜索去定位记录的时候),即使order by desc,但用的还是向右遍历,当找到了第一个等值的时候(例子中的id=15),然后根据order by desc,再向左遍历。 是不是这么理解? 问题二: 对于第21讲的思考题, select * from t where c>=15 and c<=20 order by c desc lock in share mode, 老师已经给出了答案,我这里再详细理解一下: 先定位索引c上最右边c=20的行,所以第一个等值查询会扫描到c=25,然后通过优化2,next-key lock退化为间隙锁,则会加上间隙锁(20,25),紧接着再向左遍历,会加 next-key lock (15, 20], (10, 15], 因为要扫描到c=10才停下来,所以也会加next-key lock (5,10] 理解的是否正确? 问题三: 对于上面的问题二的sql,在索引c上,把(10,25)这段区间锁上就应该是完备的了,理论上(5,10]这段区间是否锁上对结果应该没有影响呀。 是不是说MySQL就是这么实现的,next-key lock前开后闭,因为扫到了c=10,所以会加next-key lock (5,10],这里MySQL的实现扩大了锁的区间范围,其实没有这个必要? 另外,如果不加next-key lock (5,10],是不是这里c=10还是应该要锁的,如果不锁可能被删除?
作者回复: 1. 对的 2. 对的 3. “因为扫到了c=10,所以会加next-key lock (5,10]”, 对的。 第二个“如果”,实现上并不是这样的,所以没法回答😆
2019-02-11859 - Jason_鹏最后一个update的例子,为没有加(0,5)的间隙呢?我理解应该是先拿c=5去b+树搜索,按照间隙索最右原则,应该会加(0,5]的间隙,然后c=5不满足大于5条件,根据优化2原则退化成(0,5)的间隙索,我是这样理解的
作者回复: 根据c>5查到的第一个记录是c=10,因此不会加(0,5]这个next-key lock。 你提醒得对,我应该多说明这句, 我加到文稿中啦👍
2019-01-22740 - 长杰老师,之前讲这个例子时,select * from t where c>=15 and c<=20 order by c desc in share mode; 最右边加的是 (20, 25)的间隙锁, 而这个例子select * from t where id>10 and id<=15 for update中,最右边加的是(15,20]的next-key锁, 这两个查询为何最后边一个加的gap锁,一个加的next-key锁,他们都是<=的等值范围查询,区别在哪里?
作者回复: select * from t where c>=15 and c<=20 order by c desc in share mode; 这个语句是根据 c=20 来查数据的,所以加锁(20,25]的时候,可以使用优化2; select * from t where id>10 and id<=15 for update; 这里的id=20,是用“向右遍历”的方式得到的,没有优化,按照“以next-key lock”为加锁单位来执行
2019-01-221220 - ☞老师好: select * from t where c>=15 and c<=20 order by c desc for update; 为什么这种c=20就是用来查数据的就不是向右遍历 select * from t where c>=15 and c<=20 这种就是向右遍历 怎么去判断合适是查找数据,何时又是遍历呢,是因为第一个有order by desc,然后反向向左遍历了吗?所以只需要[20,25)来判断已经是最后一个20就可以了是吧
作者回复: 索引搜索就是 “找到第一个值,然后向左或向右遍历”, order by desc 就是要用最大的值来找第一个; order by就是要用做小的值来找第一个; “所以只需要[20,25)来判断已经是最后一个20就可以了是吧”, 你描述的意思是对的,但是在MySQL里面不建议写这样的前闭后开区间哈,容易造成误解。 可以描述为: “取第一个id=20后,向右遍历(25,25)这个间隙”^_^
2019-01-2217 - Long感觉这篇文章以及前面加锁的文章,提升了自己的认知。还有,谢谢老师讲解了日志的对应细节……还愿了
作者回复: 😆 👍
2019-01-2814 - 长杰老师,select * from t where id>10 and id<=15 for update;这个语句持有的锁不应该是(5,10)(10,15](15,20)吗?
作者回复: 不是哦,这里第一个id>10找到的是(10,15)这个gap,并没有加(5,10), 还有根据股则里面的“bug”,id=20也会被锁的,所以应该是(10,15](15,20]
2019-01-21213 - 唯她命老师,update语句 mysql在执行过程中 ,都是先拆成 插入 和 删除的吗?不是直接修改?
作者回复: 修改索引值都会修改位置的😆
2019-04-03210 - hal非常谢谢老师,专栏质量非常高,祝老师身体健康万事如意,因为内容写的太好了……很激动👍👍👍👍👍
作者回复: 🤝🤝🤝🤝🤝
2019-06-019