30 | 答疑文章(二):用动态的观点看加锁
30 | 答疑文章(二):用动态的观点看加锁
讲述:林晓斌
时长15:43大小14.36M
不等号条件里的等值查询
等值查询的过程
怎么看死锁?
怎么看锁等待?
update 的例子
小结
上期问题时间
赞 43
提建议
精选留言(92)
- Ryoma置顶2019-01-22删除数据,导致锁扩大的描述:“因此,我们就知道了,由于 delete 操作把 id=10 这一行删掉了,原来的两个间隙 (5,10)、(10,15)变成了一个 (5,15)。” 我觉得这个提到的(5, 10) 和 (10, 15)两个间隙会让人有点误解,实际上在删除之前间隙锁只有一个(10, 15),删除了数据之后,导致间隙锁左侧扩张成了5,间隙锁成为了(5, 15)。
作者回复: 嗯 所以我这里特别小心地没有写“锁“这个字。 间隙 (5,10)、(10,15)是客观存在的。 你提得也很对,“锁”是执行过程中才加的,是一个动态的概念。 这个问题也能够让大家更了解我们标题的意思,置顶了哈 👍
共 12 条评论148 - 令狐少侠置顶2019-01-22有个问题想确认下,在死锁日志里,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”,就是只有间隙锁;
共 2 条评论86 - IceGeek172019-02-11老师,新年好,有几个问题: 问题一: 对于文中的第一个例子(不等号条件里的等值查询),当试图去找 “第一个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]”, 对的。 第二个“如果”,实现上并不是这样的,所以没法回答😆
共 8 条评论55 - Jason_鹏2019-01-22最后一个update的例子,为没有加(0,5)的间隙呢?我理解应该是先拿c=5去b+树搜索,按照间隙索最右原则,应该会加(0,5]的间隙,然后c=5不满足大于5条件,根据优化2原则退化成(0,5)的间隙索,我是这样理解的
作者回复: 根据c>5查到的第一个记录是c=10,因此不会加(0,5]这个next-key lock。 你提醒得对,我应该多说明这句, 我加到文稿中啦👍
共 7 条评论38 - 长杰2019-01-22老师,之前讲这个例子时,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”为加锁单位来执行
共 10 条评论19 - ☞2019-01-22老师好: 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)这个间隙”^_^
17 - Long2019-01-28感觉这篇文章以及前面加锁的文章,提升了自己的认知。还有,谢谢老师讲解了日志的对应细节……还愿了
作者回复: 😆 👍
13 - Geek88192020-07-19老师,我记得之前你有说过范围查询第一次定位时用的等值查找。那select * from t where id >10 and id <= 15这条语句,首先用10去索引树查找。不应该加(5,10]这样一个记录锁么?10
- 长杰2019-01-21老师,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]
10 - 唯她命2019-04-03老师,update语句 mysql在执行过程中 ,都是先拆成 插入 和 删除的吗?不是直接修改?
作者回复: 修改索引值都会修改位置的😆
共 2 条评论8 - 库淘淘2019-01-21对于问题 我理解是这样 session 1: delete from t; begin; select * from t for update; session 2: insert into t values(1,1,1);发生等待 show engine innodb status\G; ..... ------- TRX HAS BEEN WAITING 5 SEC FOR THIS LOCK TO BE GRANTED: RECORD LOCKS space id 75 page no 3 n bits 72 index PRIMARY of table `test`.`t` trx id 752090 lock_mode X insert intention waiting Record lock, heap no 1 PHYSICAL RECORD: n_fields 1; compact format; info bits 0 0: len 8; hex 73757072656d756d; asc supremum;; 其中申请插入意向锁与间隙锁 冲突,supremum这个能否理解为 间隙右边的那个记录展开
作者回复: 发现了👍🏿
8 - 索旭东2020-03-04select * from t where id>10 and id<=15 for update; select c from t where c>5 lock in share mode; 第一条的锁是(5,10),(10,15) 第二个语句的锁是(5,10].... 两个对比,感觉矛盾了呀,第二个语句给的理由是,大于5的第一个被访问到的记录是10,同样原理第一个语句访问的第一个记录不是应该是15吗?展开共 3 条评论7
- 往事随风,顺其自然2019-06-19这么多加锁规则记不住
作者回复: 练着练着,规则就忘记了,然后直接脑补执行流程,上结论
8 - hal2019-06-01非常谢谢老师,专栏质量非常高,祝老师身体健康万事如意,因为内容写的太好了……很激动👍👍👍👍👍
作者回复: 🤝🤝🤝🤝🤝
7 - 长杰2019-01-22老师,还是select * from t where c>=15 and c<=20 order by c desc in share mode与select * from t where id>10 and id<=15 for update的问题,为何select * from t where id>10 and id<=15 for update不能解释为:根据id=15来查数据,加锁(15, 20]的时候,可以使用优化2, 这个等值查询是根据什么规则来定的? 如果select * from t where id>10 and id<=15 for update加上order by id desc是否可以按照id=15等值查询,利用优化2?多谢指教。展开
作者回复: 1. 代码实现上,传入的就是id>10里面的这个10 2. 可以的,不过因为id是主键,而且id=15这一行存在,我觉得用优化1解释更好哦
共 2 条评论7 - Yc2021-04-11老师你好,请问一下 图4的一个问题。。求解答 为啥,10不会被锁住呢?条件是id>10,查询规则是首先找到id=10的这行数据,然后根据这行数据进行向右遍历。按照加锁规则:原则 2:查找过程中访问到的对象才会加锁。 加锁的话 在根据优化1:优化 1:索引上的等值查询,给唯一索引加锁的时候,next-key lock 退化为行锁。 这个例子为啥ID=10不加锁!!!,求老师翻牌展开共 4 条评论6
- Justin2019-01-22想咨询一下 普通索引 如果索引中包括的元素都相同 在索引中顺序是怎么排解的呢 是按主键排列的吗 比如(name ,age ) 索引 name age都一样 那索引中会按照主键排序吗?
作者回复: 会的
6 - Lane2019-05-21第一个例子 begin; select * from t where id>9 and id<12 order by id desc for update; 为什么会有(0,5],不理解,但是测试确实insert into t values (3,3,3);会卡主共 4 条评论5
- 老杨同志2019-01-21先说结论:空表锁 (-supernum,supernum],老师提到过mysql的正无穷是supernum,在没有数据的情况下,next-key lock 应该是supernum前面的间隙加 supernum的行锁。但是前开后闭的区间,前面的值是什么我也不知道,就写了一个-supernum。 稍微验证一下 session 1) begin; select * from t where id>9 for update; session 2) begin; insert into t values(0,0,0),(5,5,5); (block)展开
作者回复: 赞 show engine innodb status 有惊喜😆
共 2 条评论5 - Icy:S LYZ2019-11-05难道只有我有疑问,如果唯一索引变成varchar,间隙区间会怎么选吗???还是我的问题?4