文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

【MySQL】说透锁机制(三)行锁升表锁如何避免? 锁表了如何排查?

2023-08-18 12:00

关注

前言

在上文我们曾小小的提到过,在索引失效的情况下,MySQL会把所有聚集索引记录和间隙都锁上,我们称之为锁表,或叫行锁升表锁.

那么对于 行锁升表锁,有的同学误以为行锁 升级变成了 表锁,但实际上锁的类型并没有发生变化✍️,还是行锁! 只是表的所有聚集索引记录都被加上了行锁, 看起来像表锁, 所以提前澄清一下, 举个例子:

假设,表中有10万多条记录

OK, 相信已经澄清了~ 那么对于行锁升表锁, 我们应该如何避免呢? 如果真被行锁锁表了又该如何分析排查呢? 别着急, 我们一步一步来, 干货满满, 建议先收藏!后面如果有需要了, 直接能找到这里来看.


哪些场景会造成行锁升表锁?

兵法有云:知己知彼,百战不殆!
所以在说如何避免之前,我们提前说一下哪些场景会造成行锁升表锁,建议还未看过前面两文的小伙伴先了解一下加锁规则:
【MySQL】说透锁机制(一)行锁 加锁规则 之 等值查询
【MySQL】说透锁机制(二)行锁 加锁规则 之 范围查询(你知道会锁表吗?)
那么对于看过前两篇文章的小伙伴,应该已经猜到了,场景肯定和索引有关!

没错, 就是 无索引索引失效!
那么原因呢? 你想过这里的原因吗?
在这里插入图片描述
解读:因为InnoDB引擎的 3种行锁算法(Record Lock、Gap Lock、Next-key Lock),都是锁定的索引,当触发X锁(写锁)的where条件无索引 或 索引失效 时, 查找的方式就会变成全表扫描,也就是扫描所有的聚集索引记录,到这我想大家都应该看懂了,但是可能还有个疑问,为什么要把不匹配的记录也加锁呢?
这里是针对于默认的事务隔离级别:可重复读(RR)事务隔离级别来说的, 因为在RR隔离级别下,需要解决不可重复读幻读问题, 所以在遍历扫描聚集索引记录时, 为了防止扫描过的索引被其它事务修改(不可重复读问题) 或 间隙被其它事务插入记录(幻读问题), 从而导致数据不一致, 所以MySQL的解决方案就是把所有扫描过的索引记录和间隙都锁上, 这也就 发生了我们看到的锁表!💪💪💪

在这里插入图片描述
展开来说:

无索引
例如, 下面这个sql的 remark列 不是索引列, 如果按remark更新就是无索引更新.

update ct set abc = 1 where remark = '阿根廷';

索引失效
索引失效的情况有很多, 我们本文不分析为什么失效, 也不会列举出所有失效的场景, 因为那不是本节的重点(我会考虑单独安排一篇详细讲解)。 这里直接用explain说话:

如果同时满足上面这两个条件, 那么就说明索引失效了!

对于索引失效列几个常见的场景简单说明一下:

例如,我新建一个复合索引:abc列name列,如下:

 ALTER TABLE `lock_test`.`ct` ADD INDEX `idx_abc_name`(`abc`, `name`);
但更新sql语句未按照最左前缀, 直接按`name=`更新,这样就会**导致索引失效**:
update ct set abc = 1 where name = '阿根廷';

看一下explain的结果
在这里插入图片描述

例如,我新建一个普通索引:name列

ALTER TABLE `lock_test`.`ct`ADD INDEX `idx_name`(`name`);

但更新sql语句使用了 like以%开头,这样也会导致索引失效

update ct set abc = 1 where name like '%阿根廷';

看一下explain的结果
在这里插入图片描述

这是比较特殊的情况. 同样的SQL, 传入的参数不同, explain的结果也不同, 有时会走索引, 但有时索引又失效! 😫
这里的原因:因为根据传入的参数不同 导致 结果集不同, 在正式扫描之前,MySQL会进行成本计算计算走哪个索引更快!结果一算,发现走索引还不如全表扫描快, 那么这时即使你用的是索引列等值 也不会走索引,会走全表扫描,这也就导致了索引失效
关于成本计算, 它是先计算不同索引的I/0成本和CPU成本, 然后进行对比, 哪个成本低就采用哪个索引来执行! 当然, 成本计算并不会真实执行, 所以速度非常快, 在上文【范围查询】时曾给过一个小的示例说明,这里不再重复赘述!
在这里插入图片描述

当然,索引失效的情况还有很多, 这里只是举几个例子让大家学会用explain分析, 如果不够过瘾,我后面紧接着会更新索引相关文章!记得关注我哦!


如何避免?

此时, 咱们已经清楚的知道了 可能造成 行锁升表锁 的场景,那么应对起来也就更有底气了,我的建议是:


如何分析排查?

咱们只能做到尽可能避免, 根据墨菲定律:只要有可能 就一定会发生!
所以我们必须掌握锁表应该如何分析排查

查看InnoDB_row_lock%相关变量

show status like 'innodb_row_lock%';

在这里插入图片描述

字段说明
Innodb_row_lock_current_waits当前正在等待锁定的数量
Innodb_row_lock_time等待总时长: 从系统启动到现在锁定总时间长度
Innodb_row_lock_time_avg等待平均时长: 每次等待所花平均时间
Innodb_row_lock_time_max从系统启动到现在等待最长的一次所花时间
Innodb_row_lock_waits等待总次数: 系统启动后到现在总共等待的次数

从上述值,我们可以看出我们行锁的整体情况,有助于我们分析。

查看 INFORMATION_SCHEMA系统库

我们可以通过 INFORMATION_SCHEMA系统库提供的:查看事务锁等待的 数据表 来分析.

-- 查看事务select * from INFORMATION_SCHEMA.INNODB_TRX;-- 查看锁select * from INFORMATION_SCHEMA.INNODB_LOCKS;-- 查看锁等待select * from INFORMATION_SCHEMA.INNODB_LOCK_WAITS;-- 查看连接情况select * from INFORMATION_SCHEMA.PROCESSLIST;
-- 查看锁等待select * from INFORMATION_SCHEMA.INNODB_LOCK_WAITS;
字段说明
requesting_trx_id请求的事务id
requested_lock_id请求的锁id
blocking_trx_id阻塞的事务id
blocking_lock_id阻塞的锁id

我这里模拟一个锁等待,然后查询,可以清晰的看到谁阻塞了谁
在这里插入图片描述

温馨提示:只有发生锁等待才有数据

-- 查看锁select * from INFORMATION_SCHEMA.INNODB_LOCKS;

这和我们通过show engine innodb status\G;看到的结果类似, 略…, 也是只有发生阻塞才会有数据.

 -- 查看事务 select * from INFORMATION_SCHEMA.INNODB_TRX;

这个表很关键, 对于我们排查来说必不可少, 一些关键字段说明如下:

字段说明
trx_id事务id
trx_state事务状态,LOCK WAIT代表发生了锁等待
trx_started事务开始时间
trx_requested_lock_id请求锁id, 事务当前正在等待锁的标识,可以join关联INNODB_LOCKS.lock_id
trx_wait_started事务开始锁等待的时间
trx_weight事务的权重
trx_mysql_thread_id事务线程 ID,可以join关联PROCESSLIST.ID
trx_query事务正在执行的 SQL 语句
trx_operation_state事务当前操作状态
trx_isolation_level当前事务的隔离级别

当发生阻塞时,我们来看一下数据:
在这里插入图片描述
一目了然,哪个SQL从什么时间开始阻塞,线程id是多少,看的一清二楚.

-- 查看连接情况select * from INFORMATION_SCHEMA.PROCESSLIST;

通过这个表,我们可以定位到事务所在的主机.

字段说明
ID线程ID, 可以JOIN INNODB_TRX.trx_requested_lock_id
USER连接用户
HOST连接主机 ip:port
DB连接的数据库

通过对上面的表进行查询, 当我们发现某个事务阻塞了很多事务, 并且执行时间很长时, 我们可以手动中止它, 只需要找到INNODB_TRX.trx_mysql_thread_id,然后调用kill命令:

kill {INNODB_TRX.trx_mysql_thread_id}

总结

本文主要介绍了:


最后

如果感觉不错,欢迎订阅本专栏,后面还有更详细的MySQL知识陆续放出。
关注我 天罡gg 分享更多干货: https://blog.csdn.net/scm_2008
大家的「关注 + 点赞 + 收藏」就是我创作的最大动力!谢谢大家的支持,我们下文见!


来源地址:https://blog.csdn.net/scm_2008/article/details/128461534

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     807人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     351人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     314人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     433人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     221人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-数据库
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯