文章插图
为什么事务B插入语句会阻塞,事务C的更新语句不会呢?
- 这是因为事务会话A在遍历的时候,先访问第一个c=10的记录 。它根据原则 1,加一个(c=5,id=5) 到 (c=10,id=10)的next-key lock 。
- 然后,事务会话A向右查找,直到碰到 (c=15,id=15) 这一行,循环才结束 。根据优化 2,这是一个等值查询,向右查找到了不满足条件的行,所以会退化成(c=10,id=10) 到 (c=15,id=15)的间隙Gap锁 。即事务会话A这个select...for update语句在索引 c 上的加锁范围,就是下图灰色阴影部分的:

文章插图
因为c=13是这个区间内的,所以事务B插入insert into t5 values(13,13,13);会阻塞 。因为根据优化2,已经退化成 (c=10,id=10) 到 (c=15,id=15) 的间隙Gap锁,即不包括c=15,所以事务C,Update t5 set d=d+1 where c=15不会阻塞
4.7 案例七: limit 语句减少加锁范围如果一个SQL有limit,会不会对加锁有什么影响呢?我们用4.6的例子,然后给查询语句加个limit:
Select * from t5 where c=10 limit 2 for update;事务A、B执行如下:
文章插图
发现事务B并没有阻塞,而是可以顺利执行

文章插图
这是为什么呢?跟上个例子,怎么事务B却不会阻塞了,事务会话A的select只是加多了一个limit 2 。
这是因为明确加了limit 2的限制后,因此在遍历到 (c=10, id=30) 这一行之后,满足条件的语句已经有两条,循环就结束了 。因此,索引 c上的加锁范围就变成了从(c=5,id=5) 到(c=10,id=30) 这个前开后闭区间,如下图所示:

文章插图
索引平时我们写SQL的时候,比如查询select或者delete语句时,尽量加一下limit哈 。
5. 如何查看事务加锁情况我门怎么查看SQL加了什么锁呢?或者换个说法,如何查看事务的加锁情况呢?有这两种方法:
- 使用infomation_schema数据库中的表获取锁信息
- 使用show engine innodb status
- INNODB_TRX:该表存储了InnoDB当前正在执行的事务信息,包括事务id、事务状态(比如事务是在运行还是在等待获取某个所)等
- INNODB_LOCKS:该表记录了一些锁信息,包括两个方面:1.如果一个事务想要获取某个锁,但未获取到,则记录该锁信息 。2. 如果一个事务获取到了某个锁,但是这个锁阻塞了别的事务,则记录该锁信息 。
- INNODB_LOCK_WAITS:表明每个阻塞的事务是因为获取不到哪个事务持有的锁而阻塞 。

文章插图
表中可以看到一个事务id为1644837正在运行汇中,它的隔离级别为REPEATABLE READ 。我们一般关注这几个参数:
- trx_tables_locked:该事务当前加了多少个表级锁 。
- trx_rows_locked:表示当前加了多少个行级锁 。
- trx_lock_structs:表示该事务生成了多少个内存中的锁结构 。
事务A、B执行如下:

文章插图
使用select * from
information_schema.INNODB_LOCKS;查看

文章插图
可以看到两个事务Id 1644842和1644843都持有什么锁,就是看那个lock_mode和lock_type哈 。但是并看不出是哪个锁在等待那个锁导致的阻塞,这时候就可以看INNODB_LOCK_WAITS表啦 。
5.1.3 INNODB_LOCK_WAITSINNODB_LOCK_WAITS 表明每个事务是因为获取不到哪个事务持有的锁而阻塞 。

文章插图
- requesting_trx_id:表示因为获取不到锁而被阻塞的事务的事务id
- blocking_trx_id:表示因为获取到别的事务需要的锁而导致其被阻塞的事务的事务Id 。
推荐阅读
- C语言入门算法丨冒泡排序算法详解!绝不摆烂
- 适合中国家庭的国产两厢推荐
- 如何把红茶泡好喝,咖啡红茶怎么泡
- 职业教育|职业教育想要振兴,需要改变两大关键因素
- 滇红茶耐泡,凤庆滇红茶泡法
- 卧室有两个窗户对风水有利吗?
- 卧室有两个门对我们有什么影响
- 两个动作看透你 准确率达99%!
- Windows操作系统|Win11大更新就绪:微软详解重要新功能 CPU效率暴增、全新任务管理器
- 脂肪怎么排出,教你两招懒人方法
