MySQL进阶
01、MySQL进阶:剖析MySQL索引底层数据结构
02、MySQL进阶:MySQL不同存储引擎下索引的实现
03、MySQL进阶:Explain深度剖析
04、MySQL进阶:践行索引优化
05、MySQL进阶:锁等待及死锁初探
06、MySQL进阶:无索引行锁升级为表锁
07、MySQL进阶:共享锁和排它锁初探
08、MySQL进阶:索引优化案例实操
09、MySQL进阶:索引下推IndexConditionPushdown初探
10、MySQL进阶:使用trace工具来窥探MySQL是如何选择执行计划的
11、MySQL进阶:orderby和groupby优化初探
12、MySQL进阶:分页查询优化的两个案例解析
13、MySQL进阶:Join关联查询优化
14、MySQL进阶:In和Exists的优化案例讲解
15、MySQL进阶:存储引擎初探
16、MySQL进阶:体系结构初探
17、MySQL进阶:解读MySQL事务与锁机制
18、MySQL进阶:多版本控制MVCC机制初探
19、MySQL进阶:并发事务问题及解决方案
20、MySQL进阶:锁机制初探
21、MySQL进阶:高效的设计MySQL库表
22、MySQL进阶:库表设计之IP和TIMESTAMP的处理
23、MySQL进阶:orderby出现usingfilesort根因分析及优化
24、MySQL进阶:canal实现mysql数据同步到redis|实现自定义canal客户端
本文档使用 MrDoc 发布
-
+
首页
05、MySQL进阶:锁等待及死锁初探
 ------------ ### **版本信息** ```python mysql> select version(); +-----------+ | version() | +-----------+ | 5.7.28 | +-----------+ 1 row in set mysql> ``` ------------ ### **MySQL 行锁分析** ```python mysql> show status like'innodb_row_lock%'; +-------------------------------+--------+ | Variable_name | Value | +-------------------------------+--------+ | Innodb_row_lock_current_waits | 0 | | Innodb_row_lock_time | 222821 | | Innodb_row_lock_time_avg | 27852 | | Innodb_row_lock_time_max | 51017 | | Innodb_row_lock_waits | 8 | +-------------------------------+--------+ 5 rows in set mysql> ``` **变量说明:** - Innodb_row_lock_current_waits 当前正在等待锁定的数量 单位毫秒 - Innodb_row_lock_time 从系统启动到现在锁定总时间长度 单位毫秒 - Innodb_row_lock_time_avg 每次等待所花平均时间 单位毫秒 - Innodb_row_lock_time_max 从系统启动到现在等待最长的一次所花时间 单位毫秒 - Innodb_row_lock_waits 系统启动后到现在总共等待的次数 重点关注 : Innodb_row_lock_time_avg 、Innodb_row_lock_waits 、Innodb_row_lock_time ------------ ### **MySQL死锁演示** **事务隔离级别, 默认 可重复读** ```python mysql> show variables like '%tx_isolation%'; +---------------+-----------------+ | Variable_name | Value | +---------------+-----------------+ | tx_isolation | REPEATABLE-READ | +---------------+-----------------+ 1 row in set mysql> ``` 【操作步骤】 | session1 | session2 | | --- | --- | | begin 模拟开启事务 | | | select * from art_info where id=1 for update; | | | | begin 模拟开启事务 | | | select * from account where id=2 for update; | | select * from art_info where id=2 for update; ---->一直等待 | | | | select * from art_info where id=1 for update; —> Deadlock found when trying to get lock; try restarting transaction | **大多数情况mysql可以自动检测死锁并回滚产生死锁的那个事务,但是有些情况mysql没法自动检测死锁** ------------ ### **排查过程** 【模拟锁等待 】 | session1 | session2 | | --- | --- | | begin 模拟开启事务 | | | select * from art_info where id=1 for update; | | | | begin 模拟开启事务 | | | select * from account where id=2 for update; | | select * from account where id=2 for update; | | ```python mysql> select * from art_info where id =2 for update ; 1205 - Lock wait timeout exceeded; try restarting transaction ``` ```python -- 查看事务 select * from information_schema.INNODB_TRX; -- 查看锁 select * from information_schema.INNODB_LOCKS; -- 查看锁等待 select * from information_schema.INNODB_LOCK_WAITS; -- 锁释放 information_schema.INNODB_TRX 查询 trx_mysql_thread_id 然后去 kill 对应的value kill trx_mysql_thread_id ``` 来吧,用上面的SQL查吧    ### **查看近期死锁日志信息** ------------ ```python show engine innodb status \G; ```  ------------ ### **查询锁等待命令及kill 锁** ```python -- 查看事务 select * from information_schema.INNODB_TRX; -- 查看锁 select * from information_schema.INNODB_LOCKS; -- 查看锁等待 select * from information_schema.INNODB_LOCK_WAITS; -- 锁释放 information_schema.INNODB_TRX 查询 trx_mysql_thread_id 然后去 kill 对应的value kill trx_mysql_thread_id ```  **锁等待有自己的超时时间,超过后一般都会自动释放** ```python mysql> select * from art_info where id =2 for update ; 1205 - Lock wait timeout exceeded; try restarting transaction ``` ------------ ### **优化建议** - 尽可能让所有数据检索都通过索引来完成,避免无索引行锁升级为表锁 - 合理设计索引,尽量缩小锁的范围 - 尽可能减少检索条件范围,避免间隙锁 - 尽量控制事务大小,减少锁定资源量和时间长度,涉及事务加锁的sql尽量放在事务最后执行 - 尽可能低级别事务隔离
李智
2025年3月17日 13:31
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
Markdown文件
分享
链接
类型
密码
更新密码